day08 文章详情页设计

文章详情页

# url设计
/username/article/1

# 先验证url是否会被其他url顶替

# 文章详情页和个人站点基本一致 所以用模版继承

# 侧边栏的渲染需要传输数据才能渲染 并且该侧边栏在很多页面都需要使用
	1.哪个地方用就拷贝需要的代码(不推荐 有点繁琐)
  
  2.将侧边栏制作成inclusion_tag	
  """
  步骤
  	1.在应用下创建一个名字必须叫templatetags文件夹
  	2.在该文件夹内创建一个任意名称的py文件
  	3.在该py文件内先固定写两行代码
  		from django import template
  		register = template.Library()
  		# 自定义过滤器
  		# 自定义标签
  		# 自定义inclusion_tag
  
  """
  # 自定义inclusion_tag
@register.inclusion_tag('left_menu.html')
def left_menu(username):
    # 构造侧边栏需要的数据
    user_obj = models.UserInfo.objects.filter(username=username).first()
    blog = user_obj.blog
    # 1 查询当前用户所有的分类及分类下的文章数
    category_list = models.Category.objects.filter(blog__userinfo__username=username).annotate(count_num=Count('article__pk')).values_list('title','count_num','pk')
    # print(category_list)  # <QuerySet [('jason的分类一', 2), ('jason的分类二', 1), ('jason的分类三', 1)]>

    # 2 查询当前用户所有的标签及标签下的文章数
    tag_list = models.Tag.objects.filter(blog__userinfo__username=username).annotate(count_num=Count('article__pk')).values_list('title','count_num','pk')
    # print(tag_list)  # <QuerySet [('tank的标签一', 1), ('tank的标签二', 1), ('tank的标签三', 2)]>

    # 3 按照年月统计所有的文章
    date_list = models.Article.objects.filter(user__username=username).annotate(month=TruncMonth('create_time')).values('month').annotate(count_num=Count('pk')).values_list('month','count_num')
    # print(date_list)
    return locals()


侧边栏页面渲染left_menu.html

 <div class="panel panel-primary">
          <div class="panel-heading">
            <h3 class="panel-title">文章分类</h3>
          </div>
          <div class="panel-body">
                {% for category in category_list %}
                    <p><a href="/{{ username }}/category/{{ category.2 }}">{{ category.0 }}({{ category.1 }})</a></p>
                {% endfor %}
          </div>
        </div>
 <div class="panel panel-danger">
          <div class="panel-heading">
            <h3 class="panel-title">文章标签</h3>
          </div>
          <div class="panel-body">
              {% for tag in tag_list %}
                <p><a href="/{{ username }}/tag/{{ tag.2 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
              {% endfor %}

          </div>
        </div>
 <div class="panel panel-info">
          <div class="panel-heading">
            <h3 class="panel-title">日期归档</h3>
          </div>
          <div class="panel-body">
              {% for date in date_list %}
                <p><a href="/{{ username }}/archive/{{ date.0|date:'Y-m' }}">{{ date.0|date:'Y年m月' }}({{ date.1 }})</a></p>
              {% endfor %}
          </div>
        </div>

将首页框架放入base.html文件中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/media/css/{{ blog.site_theme }}/">
    {% block css %}

    {% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">{{ blog.site_title }}</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">博客 <span class="sr-only">(current)</span></a></li>
                <li><a href="#">文章</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多 <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li><a href="#">{{ request.user.username }}</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">更多操作 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#" data-toggle="modal" data-target=".bs-example-modal-lg">修改密码</a></li>
                            <li><a href="#">修改头像</a></li>
                            <li><a href="#">后台管理</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="{% url 'logout' %}">退出登陆</a></li>
                        </ul>

                        <div class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
                            <div class="modal-dialog modal-lg" role="document">
                                <div class="modal-content">
                                    <h1 class="text-center">修改密码</h1>
                                    <div class="row">
                                        <div class="col-md-8 col-md-offset-2">
                                            <div class="form-group">
                                                <label for="">用户名</label>
                                                <input type="text" disabled value="{{ request.user.username }}" class="form-control">
                                            </div>
                                            <div class="form-group">
                                                <label for="">原密码</label>
                                                <input type="password" id="id_old_password" class="form-control">
                                            </div>
                                            <div class="form-group">
                                                <label for="">新密码</label>
                                                <input type="password" id="id_new_password" class="form-control">
                                            </div>
                                            <div class="form-group">
                                                <label for="">确认密码</label>
                                                <input type="password" id="id_confirm_password" class="form-control">
                                            </div>
                                            <div class="modal-footer">
                                                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                                                <button class="btn btn-primary" id="id_edit">修改</button>
                                                <span style="color: red" id="password_error"></span>
                                            </div>
                                            <br>
                                            <br>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </li>
                {% else %}
                    <li><a href="{% url 'reg' %}">注册</a></li>
                    <li><a href="{% url 'login' %}">登陆</a></li>
                {% endif %}
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            {% load mytag %}
            {% left_menu username %}
        </div>
        <div class="col-md-9">
            {% block content %}

            {% endblock %}

        </div>
    </div>
</div>

{% block js %}

{% endblock %}
</body>
</html>

视图view.py

def article_detail(request,username,article_id):
    """
   应该需要校验username和article_id是否存在,但是我们这里先只完成正确的情况
   默认不会瞎搞
   :param request:
   :param username:
   :param article_id:
   :return:
   """
    user_obj = models.UserInfo.objects.filter(username=username).first()
    blog = user_obj.blog
    # 先获取文章对象
    article_obj = models.Article.objects.filter(pk=article_id,user__username=username).first()
    if not article_obj:
        return render(request,'errors.html')
    return render(request,'article_detail.html',locals())

文章详情页面渲染 article_detail.html

{% extends  'base.html' %}

{% block content %}
    <h1>{{ article_obj.title }}</h1>
    <div class="article_content">
        {{ article_obj.content|safe }}
    </div>

{% endblock %}

个人站点页面渲染优化
将视图侧边栏逻辑注释

site.html

{% extends 'base.html' %}


{% block content %}
    <ul class="media-list">
        {% for article_obj in article_list %}
            <li class="media">
                <h4 class="media-heading"><a href="/{{ username }}/article/{{ article_obj.pk }}/">{{ article_obj.title }}</a></h4>
                <div class="media-left">
                    <a href="#">
                        <img class="media-object" src="/media/{{ article_obj.user.avatar }}" alt="..." width="80">
                    </a>
                </div>
                <div class="media-body">
                    {{ article_obj.desc }}
                </div>
                {#                posted @ 2015-10-20 01:02 wahaha 阅读(68527) 评论(24) 推荐(58) 编辑)#}
                <div class="pull-right">
                    <span>posted&nbsp;&nbsp;</span>
                    <span>@&nbsp;&nbsp;</span>
                    <span>{{ article_obj.create_time|date:'Y-m-d' }}&nbsp;&nbsp;</span>
                    <span>{{ article_obj.user.username }}&nbsp;&nbsp;</span>
                    <span><span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_count }})&nbsp;&nbsp;</span>
                    <span><span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_count }})</span>
                    <span><a href="#">编辑</a></span>
                </div>
            </li>
            <hr>
        {% endfor %}

    </ul>
{% endblock %}

路由设置

    # 文章详情页
    url(r'^(?P<username>\w+)/article/(?P<article_id>\d+)/',views.article_detail)

文章点赞点踩

"""
浏览器上你看到的花里胡哨的页面,内部都是HTML(前端)代码

那现在我们的文章内容应该写什么???	>>> html代码

如何拷贝文章
	copy outerhtml

1.拷贝文章
2.拷贝点赞点踩
	1.拷贝前端点赞点踩图标 只拷了html
	2.css也要拷贝
		由于有图片防盗链的问题 所以将图片直接下载到本地

课下思考:
	前端如何区分用户是点了赞还是点了踩
	1.给标签各自绑定一个事件
		两个标签对应的代码其实基本一样,仅仅是是否点赞点踩这一个参数不一样而已
	2.二合一
		给两个标签绑定一个事件
		//   给所有的action类绑定事件
  	$('.action').click(function () {
            alert($(this).hasClass('diggit'))
        })

由于点赞点踩内部有一定的业务逻辑,所以后端单独开设视图函数处理

"""
# 个人建议:写代码先把所有正确的逻辑写完再去考虑错误的逻辑 不要试图两者兼得
import json
from django.db.models import F
def up_or_down(request):
    """
    1.校验用户是否登陆
    2.判断当前文章是否是当前用户自己写的(自己不能点自己的文章)
    3.当前用户是否已经给当前文章点过了
    4.操作数据库了
    :param request:
    :return:
    """
    if request.is_ajax():
        back_dic = {'code': 1000, 'msg': ''}
        # 1 先判断当前用户是否登陆
        if request.user.is_authenticated:
            article_id = request.POST.get('article_id')
            is_up = request.POST.get('is_up')
            # print(is_up,type(is_up))  # true <class 'str'>
            is_up = json.loads(is_up)  # 记得转换
            # print(is_up, type(is_up))  # True <class 'bool'>
            # 2 判断当前文章是否是当前用户自己写的  根据文章id查询文章对象 根据文章对象查作者 根request.user比对
            article_obj = models.Article.objects.filter(pk=article_id).first()
            if not article_obj.user == request.user:
                # 3 校验当前用户是否已经点了      哪个地方记录了用户到底点没点
                is_click = models.ArticleUpDown.objects.filter(user=request.user, article=article_obj)
                if not is_click:
                    # 4 操作数据库 记录数据      要同步操作普通字段
                    # 判断当前用户点了赞还是踩 从而决定给哪个字段加一
                    if is_up:
                        # 给点赞数加一
                        models.Article.objects.filter(pk=article_id).update(up_count=F('up_count') + 1)
                        back_dic['msg'] = '点赞成功'
                    else:
                        # 给点踩数加一
                        models.Article.objects.filter(pk=article_id).update(down_count=F('down_count') + 1)
                        back_dic['msg'] = '点踩成功'
                    # 操作点赞点踩表
                    models.ArticleUpDown.objects.create(user=request.user, article=article_obj, is_up=is_up)
                else:
                    back_dic['code'] = 1001
                    back_dic['msg'] = '你已经点过了,不能再点了'  # 这里你可以做的更加的详细 提示用户到底点了赞还是点了踩
            else:
                back_dic['code'] = 1002
                back_dic['msg'] = '你个臭不要脸的!'
        else:
            back_dic['code'] = 1003
            back_dic['msg'] = '请先<a href="/login/">登陆</a>'
        return JsonResponse(back_dic)

<script>
        //   给所有的action类绑定事件
        $('.action').click(function () {
            {#alert($(this).hasClass('diggit'))#}
            let isUp = $(this).hasClass('diggit');
            let $div = $(this);
            // 朝后端发送ajax请求
            $.ajax({
                url:'/up_or_down/',
                type:'post',
                data:{
                    'article_id':'{{ article_obj.pk }}',
                    'is_up':isUp,
                    'csrfmiddlewaretoken':'{{ csrf_token }}'
                },
                success:function (args) {
                        if(args.code == 1000){
                            $('#digg_tips').text(args.msg)
                            // 将前端的数字加一
                            // 先获取到之前的数字
                            let oldNum = $div.children().text();  // 文本 是字符类型
                            // 易错点
                            $div.children().text(Number(oldNum) + 1)  // 字符串拼接了 1+1 = 11  11 + 1 = 111
                        }else{
                            $('#digg_tips').html(args.msg)
                        }
                }
            })
        })
    </script>

url.py

    #点赞点踩
    url(r'up_or_down',views.up_or_down),

包含点赞点踩页面渲染article_detail.html

{% extends  'base.html' %}

{% block css %}
    <style>
        #div_digg {
            float: right;
            margin-bottom: 10px;
            margin-right: 30px;
            font-size: 12px;
            width: 125px;
            text-align: center;
            margin-top: 10px;
        }

        .diggit {
            float: left;
            width: 46px;
            height: 52px;
            background: url('/static/img/upup.gif') no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .buryit {
            float: right;
            margin-left: 20px;
            width: 46px;
            height: 52px;
            background: url('/static/img/downdown.gif') no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .clear {
            clear: both;
        }

    </style>


{% endblock %}

{% block content %}
    <h1>{{ article_obj.title }}</h1>
    <div class="article_content">
        {{ article_obj.content|safe }}
    </div>
    {#    点赞点踩样式开始#}
    <div>
        <div id="div_digg">
            <div class="diggit action" >
                <span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
            </div>
            <div class="buryit action" >
                <span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
            </div>
            <div class="clear"></div>
            <div class="diggword" id="digg_tips">
            </div>
        </div>
    </div>
    {#    点赞点踩样式结束#}
{% endblock %}

{% block js %}
    <script>
        //   给所有的action类绑定事件
        $('.action').click(function () {
            {#alert($(this).hasClass('diggit'))#}
            let isUp = $(this).hasClass('diggit');
            let $div = $(this);
            // 朝后端发送ajax请求
            $.ajax({
                url: '/up_or_down/',
                type: 'post',
                data: {
                    'article_id': '{{ article_obj.pk }}',
                    'is_up': isUp,
                    'csrfmiddlewaretoken': '{{ csrf_token }}'
                },
                success: function (args) {
                    if (args.code == 1000) {
                        $('#digg_tips').text(args.msg)
                        // 将前端的数字加一
                        // 先获取到之前的数字
                        let oldNum = $div.children().text();  // 文本 是字符类型
                        // 易错点
                        $div.children().text(Number(oldNum) + 1)  // 字符串拼接了 1+1 = 11  11 + 1 = 111
                    } else {
                        $('#digg_tips').html(args.msg)
                    }
                }
            })
        })
    </script>
{% endblock %}

文章评论

"""
我们先写根评论
再写子评论

点击评论按钮需要将评论框里面的内容清空

根评论有两步渲染方式
	1.DOM临时渲染
	2.页面刷新render渲染

子评论
	点击回复按钮发生了几件事
		1.评论框自动聚焦
		2.将回复按钮所在的那一行评论人的姓名
			@username
		3.评论框内部自动换行
	
根评论子评论都是点击一个按钮朝后端提交数据的
	parent_id
根评论子评论区别在哪?
	parent_id
"""

文章详情视图增加查询评论列表sql

    # 获取当前 文章所有的评论内容
    comment_list = models.Comment.objects.filter(article=article_obj)

view.py相关视图参考

def article_detail(request, username, article_id):
    """
   应该需要校验username和article_id是否存在,但是我们这里先只完成正确的情况
   默认不会瞎搞
   :param request:
   :param username:
   :param article_id:
   :return:
   """
    user_obj = models.UserInfo.objects.filter(username=username).first()
    blog = user_obj.blog
    # 先获取文章对象
    article_obj = models.Article.objects.filter(pk=article_id, user__username=username).first()
    if not article_obj:
        return render(request, 'errors.html')
    # 获取当前 文章所有的评论内容
    comment_list = models.Comment.objects.filter(article=article_obj)
    return render(request, 'article_detail.html', locals())

from django.db.models import F
from django.db import transaction
def comment(request):
    # 自己也可以给自己的文章评论内容
    if request.is_ajax():
        back_dic = {'code': 1000, 'msg': ""}
        if request.method == 'POST':
            if request.user.is_authenticated:
                article_id = request.POST.get('article_id')
                content = request.POST.get("content")
                parent_id = request.POST.get('parent_id')
                # 直接操作评论表 存储数据      两张表
                with transaction.atomic():
                    models.Article.objects.filter(pk=article_id).update(comment_count=F('comment_count') + 1)
                    models.Comment.objects.create(user=request.user, article_id=article_id, content=content,
                                                  parent_comment_id=parent_id)
                back_dic['msg'] = '评论成功'
            else:
                back_dic['code'] = 1001
                back_dic['msg'] = '用户未登陆'
            return JsonResponse(back_dic)

url.py

    #评论
    url(r'comment',views.comment),

article_detail.html文章详情

{% extends  'base.html' %}

{% block css %}
    <style>
        #div_digg {
            float: right;
            margin-bottom: 10px;
            margin-right: 30px;
            font-size: 12px;
            width: 125px;
            text-align: center;
            margin-top: 10px;
        }

        .diggit {
            float: left;
            width: 46px;
            height: 52px;
            background: url(/static/img/upup.gif) no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .buryit {
            float: right;
            margin-left: 20px;
            width: 46px;
            height: 52px;
            background: url(/static/img/downdown.gif) no-repeat;
            text-align: center;
            cursor: pointer;
            margin-top: 2px;
            padding-top: 5px;
        }

        .clear {
            clear: both;
        }

    </style>


{% endblock %}

{% block content %}
    <h1>{{ article_obj.title }}</h1>
    <div class="article_content">
        {{ article_obj.content|safe }}
    </div>
    {#    点赞点踩样式开始#}
    <div>
        <div id="div_digg">
            <div class="diggit action" >
                <span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
            </div>
            <div class="buryit action" >
                <span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
            </div>
            <div class="clear"></div>
            <div class="diggword" id="digg_tips">
            </div>
        </div>
    </div>
    {#    点赞点踩样式结束#}
    {#    评论楼渲染开始#}
    {#    #3楼 2020-05-14 14:11 代码一字狂#}
    <div>
        <ul class="list-group">
            {% for comment in comment_list %}
                <li class="list-group-item">
                    <span>#{{ forloop.counter }}楼</span>
                    <span>{{ comment.create_time|date:'Y-m-d h:i:s' }}</span>
                    <span>{{ comment.user.username }}</span>
                    <span><a class="pull-right reply" username="{{ comment.user.username }}" nid="{{ comment.pk }}">回复</a></span>
                    <div>
                        {#                判断当前评论是否是子评论 如果是需要渲染对应的评论人名#}
                        {% if comment.parent_comment_id %}
                            <p>@{{ comment.parent_comment.user.username }}</p>
                        {% endif %}
                        {{ comment.content }}
                    </div>
                </li>
            {% endfor %}
        </ul>


    </div>
    {#    评论楼渲染结束#}
    {#   文章评论样式开始 #}
    {% if request.user.is_authenticated %}
        <div>
            <p><span class="glyphicon glyphicon-comment"></span>发表评论</p>
            <div>
                <textarea name="comment" id="id_comment" cols="60" rows="10" ></textarea>
            </div>
            <button class="btn btn-primary" id="id_submit">提交评论</button>
            <span style="color: red" id="errors"></span>
        </div>
    {% else %}
        <li><a href="{% url 'reg' %}">注册</a></li>
        <li><a href="{% url 'login' %}">登陆</a></li>
    {% endif %}
    {#   文章评论样式结束 #}
{% endblock %}

{% block js %}
    <script>
        //   给所有的action类绑定事件
        $('.action').click(function () {
            {#alert($(this).hasClass('diggit'))#}
            let isUp = $(this).hasClass('diggit');
            let $div = $(this);
            // 朝后端发送ajax请求
            $.ajax({
                url: '/up_or_down/',
                type: 'post',
                data: {
                    'article_id': '{{ article_obj.pk }}',
                    'is_up': isUp,
                    'csrfmiddlewaretoken': '{{ csrf_token }}'
                },
                success: function (args) {
                    if (args.code == 1000) {
                        $('#digg_tips').text(args.msg)
                        // 将前端的数字加一
                        // 先获取到之前的数字
                        let oldNum = $div.children().text();  // 文本 是字符类型
                        // 易错点
                        $div.children().text(Number(oldNum) + 1)  // 字符串拼接了 1+1 = 11  11 + 1 = 111
                    } else {
                        $('#digg_tips').html(args.msg)
                    }
                }
            })
        })
        // 设置一个全局的parentID字段
        let parentId = null;
        // 用户点击评论按钮朝后端发送ajax请求
        $('#id_submit').click(function () {
            // 获取用户评论的内容
            let conTent = $('#id_comment').val();
            // 判断当前评论是否是子评论 如果是 需要将我们之前手动渲染的@username去除
            if(parentId){
                // 找到\n对应的索引 然后利用切片 但是前片顾头不顾尾 所以索引+1
                let indexNum = conTent.indexOf('\n') + 1;
                conTent = conTent.slice(indexNum)  // 将indexNum之前的所有数据切除 只保留后面的部分
            }
            $.ajax({
                url:'/comment/',
                type:'post',
                data:{
                    'article_id':'{{ article_obj.pk }}',
                    'content':conTent,
                    // 如果parantId没有值 那么就是null 后端存储null没有任何关系
                    'parent_id':parentId,
                    'csrfmiddlewaretoken':'{{ csrf_token }}'
                },
                success:function (args) {
                    if(args.code ==1000){
                        $('#error').text(args.msg)

                        // 将评论框里面的内容清空
                        $('#id_comment').val('');

                        // 临时渲染评论楼
                        let userName = '{{ request.user.username }}';
                        let temp = `
                        <li class="list-group-item">

                            <span>${userName}</span>
                            <span><a href="#" class="pull-right">回复</a></span>
                            <div>
                                ${conTent}
                            </div>
                            </li>
                        `
                        // 将生成好的标签添加到ul标签内
                        $('.list-group').append(temp);
                        // 清空全局的parentId
                        parentId = null;
                    }
                }
            })
        })
        // 给回复按钮绑定点击事件
        $('.reply').click(function () {
            // 需要评论对应的评论人姓名   还需要评论的主键值
            // 获取用户名
            let commentUserName = $(this).attr('username');
            // 获取主键值 直接修改全局
            parentId = $(this).attr('nid');
            // 拼接信息塞给评论框
            $('#id_comment').val('@' + commentUserName + '\n').focus()
        })
    </script>
{% endblock %}
posted @   simon_T  阅读(106)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示