评论功能实现

实现了一个包括添加表情和回复评论功能的评论区

html部分:

<v-sheet ref="comment_area" color="rgba(255,255,255,0.5)">
                      <v-container>
                        <span style="font-weight: bold; font-family: 微软雅黑,serif; font-size: 22px">评论</span>
                        <!--                        评论输入框-->
                        <div style="padding-top: 1vh">
                          <a-textarea
                            id="comm"
                            style="background-color: rgba(255,255,255,0.5)"
                            v-model="comment_content"
                            placeholder='请发表有价值的评论'
                            :auto-size="{ minRows: 4, maxRows: 6 }"
                            @onchange="word_limit($event)"
                            @onkeydown="word_limit($event)"
                            :onkeyup="word_limit()"
                          />
                          <v-row no-gutters justify-lg="end">
                            <v-col cols="12" lg="9" style="text-align: left">
                              <v-subheader>
                                还可输入&nbsp;&nbsp;<span style="color: #2C2E2D">{{input_length}}</span>&nbsp;&nbsp;个字符
                              </v-subheader>
                            </v-col>
                            <v-col cols="12" lg="1" style="text-align: right">
                              <v-subheader>
                                <v-menu scale offset-y>
                                  <template v-slot:activator="{ on, attrs }">
                                    <v-btn v-bind="attrs" v-on="on" icon @click="picker_selected = 'comm'">
                                      <v-icon>mdi-emoticon</v-icon>
                                    </v-btn>
                                  </template>
                                  <!--                          评论输入框的表情选择器-->
                                  <picker
                                    style="height: 25vh"
                                    :include="['people','Smileys']"
                                    :showSearch="false"
                                    :showPreview="false"
                                    :showCategories="false"
                                    @select="addEmoji"
                                  />
                                </v-menu>
                              </v-subheader>
                            </v-col>
                            <v-col cols="12" lg="2" style="text-align: center">
                              <v-subheader>
                                <v-btn rounded outlined color="grey" width="8vw" @click="send_comment">
                                  <span style="color: #2C2E2D">发表评论</span>
                                </v-btn>
                              </v-subheader>
                            </v-col>
                          </v-row>
                        </div>
                        <v-list three-line :key="children_show" style="background-color: #F9F9F3">
                          <template v-for="(item, index) in comment_list">
                            <v-divider></v-divider>
                            <v-list-item :key="index">
                              <v-list-item-avatar size="32" @click="visitUser(item.userId)" style="cursor: pointer">
                                <v-img :src="item.profilepic"></v-img>
                              </v-list-item-avatar>
                              <v-list-item-content>
                                <v-list-item-subtitle style="padding-bottom: 1vh">
                                  <v-row no-gutters>
                                    <v-col cols="12" lg="6" style="text-align: left">
                                      <span @click="visitUser(item.userId)" style="cursor: pointer">{{item.nickname}}</span>
                                      &nbsp;&nbsp;&nbsp;&nbsp;<span>{{item.relativeTime}}</span>
                                    </v-col>
                                    <v-col cols="12" lg="4"></v-col>
                                    <!--                                    评论删除按钮-->
                                    <v-col cols="12" lg="1">
                                      <v-dialog
                                        max-width="370"
                                      >
                                        <template v-slot:activator="{ on, attrs }">
                                          <a type="text" style="color: #2C2E2D"
                                             v-bind="attrs"
                                             v-on="on"
                                             v-if="isMine || item.mine">
                                            <v-icon left size="18px">mdi-delete-empty-outline</v-icon>
                                            <span>删除</span>
                                          </a>
                                        </template>
                                        <template v-slot:default="dialog">
                                          <v-card>
                                            <v-card-title>
                                              删除评论
                                            </v-card-title>
                                            <v-card-text>确认删除“{{item.nickname}}”的评论吗?</v-card-text>
                                            <br><br>
                                            <v-card-actions>
                                              <v-spacer></v-spacer>
                                              <v-btn text @click="dialog.value = false">
                                                取消
                                              </v-btn>
                                              <v-btn text @click="delete_comment(item,dialog)" color="#A94600">
                                                确认
                                              </v-btn>
                                            </v-card-actions>
                                          </v-card>
                                        </template>
                                      </v-dialog>
                                    </v-col>
                                    <!--                                    顶级评论的回复和收起按钮-->
                                    <v-col cols="12" lg="1">
                                      <a type="text" style="color: #2C2E2D" @click="show_reply(item)" v-if="!item.show_input">
                                        <v-icon left size="18px">mdi-comment-outline</v-icon>
                                        <span>回复</span>
                                      </a>
                                      <a type="text" style="color: #2C2E2D" @click="hide_reply(item)" v-else>
                                        <v-icon left size="18px">mdi-comment-outline</v-icon>
                                        <span>收起</span>
                                      </a>
                                    </v-col>
                                  </v-row>
                                </v-list-item-subtitle>
                                <p style="line-height: 20px; white-space: pre-line">{{item.content}}</p>
                                <!--                                顶级评论的回复框-->
                                <div style="padding-top: 1vh" v-if="item.show_input">
                                  <a-textarea
                                    :id="item.id"
                                    v-model="children_comment_content"
                                    style="background-color: rgba(255,255,255,0.5)"
                                    placeholder='回复'
                                    :auto-size="{ minRows: 3, maxRows: 5 }"
                                    @onchange="reply_word_limit($event)"
                                    @onkeydown="reply_word_limit($event)"
                                    :onkeyup="reply_word_limit()"
                                  />
                                  <v-row no-gutters justify-lg="end">
                                    <v-col cols="12" lg="9" style="text-align: left">
                                      <v-subheader>
                                        还可输入&nbsp;&nbsp;<span style="color: #2C2E2D">{{reply_length}}</span>&nbsp;&nbsp;个字符
                                      </v-subheader>
                                    </v-col>
                                    <v-col cols="12" lg="1" style="text-align: right">
                                      <v-subheader>
                                        <v-menu scale offset-y>
                                          <template v-slot:activator="{ on, attrs }">
                                            <v-btn v-bind="attrs" v-on="on" icon @click="picker_selected = item.id">
                                              <v-icon>mdi-emoticon</v-icon>
                                            </v-btn>
                                          </template>
                                          <!--                                          顶级评论的回复框的表情选择器-->
                                          <picker
                                            style="height: 25vh"
                                            :include="['people','Smileys']"
                                            :showSearch="false"
                                            :showPreview="false"
                                            :showCategories="false"
                                            @select="addEmoji"
                                          />
                                        </v-menu>
                                      </v-subheader>
                                    </v-col>
                                    <v-col cols="12" lg="2" style="text-align: center">
                                      <v-subheader>
                                        <v-btn rounded outlined color="grey" width="6vw" @click="reply_comment(item.id,item.id)">
                                          <span style="color: #2C2E2D">回复</span>
                                        </v-btn>
                                      </v-subheader>
                                    </v-col>
                                  </v-row>
                                </div>
                                <!--                                子评论列表-->
                                <div v-if="item.children.length!==0">
                                  <el-button
                                    v-if="item.show_children===false"
                                    type="text"
                                    @click="item.show_children=true;children_show += 1"
                                  >
                                    <span style="color: #89B8CA; font-family: 微软雅黑,serif; letter-spacing: 1px">
                                      查看全部{{item.children.length}}条回复
                                    </span>
                                  </el-button>
                                  <v-list v-else style="background-color: #F9F9F3">
                                    <template v-for="(child_item, index) in item.children">
                                      <v-divider></v-divider>
                                      <v-list-item :key="index">
                                        <v-list-item-avatar size="28" @click="visitUser(child_item.userId)" style="cursor: pointer">
                                          <v-img :src="child_item.profilepic"></v-img>
                                        </v-list-item-avatar>
                                        <v-list-item-content>
                                          <v-list-item-subtitle style="padding-bottom: 1vh">
                                            <v-row no-gutters>
                                              <v-col cols="12" lg="6" style="text-align: left">
                                                <span @click="visitUser(child_item.userId)" style="cursor: pointer">{{child_item.nickname}}</span>
                                                <span style="color: #89B8CA">&nbsp;回复&nbsp;</span>
                                                <span @click="visitUser(child_item.puserId)" style="cursor: pointer">{{child_item.pnickname}}</span>
                                                &nbsp;&nbsp;&nbsp;&nbsp;{{child_item.relativeTime}}
                                              </v-col>
                                              <v-col cols="12" lg="4"></v-col>
                                              <v-col cols="12" lg="1">
                                                <v-dialog
                                                  max-width="370"
                                                >
                                                  <template v-slot:activator="{ on, attrs }">
                                                    <a type="text" style="color: #2C2E2D"
                                                       v-bind="attrs"
                                                       v-on="on"
                                                       v-if="isMine || child_item.mine">
                                                      <v-icon left size="18px">mdi-delete-empty-outline</v-icon>
                                                      <span>删除</span>
                                                    </a>
                                                  </template>
                                                  <template v-slot:default="dialog">
                                                    <v-card>
                                                      <v-card-title>
                                                        删除评论
                                                      </v-card-title>
                                                      <v-card-text>确认删除“{{child_item.nickname}}”的评论吗?</v-card-text>
                                                      <br><br>
                                                      <v-card-actions>
                                                        <v-spacer></v-spacer>
                                                        <v-btn text @click="dialog.value = false">
                                                          取消
                                                        </v-btn>
                                                        <v-btn text @click="delete_comment(child_item,dialog)" color="#A94600">
                                                          确认
                                                        </v-btn>
                                                      </v-card-actions>
                                                    </v-card>
                                                  </template>
                                                </v-dialog>
                                              </v-col>
                                              <v-col cols="12" lg="1">
                                                <a style="color: #2C2E2D" @click="show_reply(child_item)" v-if="!child_item.show_input">
                                                  <v-icon left size="18px">mdi-comment-outline</v-icon>
                                                  回复
                                                </a>
                                                <a type="text" style="color: #2C2E2D" @click="hide_reply(child_item)" v-else>
                                                  <v-icon left size="18px">mdi-comment-outline</v-icon>
                                                  <span>收起</span>
                                                </a>
                                              </v-col>
                                            </v-row>
                                          </v-list-item-subtitle>
                                          <p style="line-height: 20px; white-space: pre-line">{{child_item.content}}</p>
                                          <!--                                          子评论的回复框-->
                                          <div style="padding-top: 1vh" v-if="child_item.show_input">
                                            <a-textarea
                                              :id="child_item.id"
                                              v-model="children_comment_content"
                                              placeholder='回复'
                                              style="background-color: rgba(255,255,255,0.5)"
                                              :auto-size="{ minRows: 3, maxRows: 5 }"
                                              @onchange="reply_word_limit($event)"
                                              @onkeydown="reply_word_limit($event)"
                                              :onkeyup="reply_word_limit()"
                                            />
                                            <v-row no-gutters justify-lg="end">
                                              <v-col cols="12" lg="9" style="text-align: left">
                                                <v-subheader>
                                                  还可输入&nbsp;&nbsp;<span style="color: #2C2E2D">{{reply_length}}</span>&nbsp;&nbsp;个字符
                                                </v-subheader>
                                              </v-col>
                                              <v-col cols="12" lg="1" style="text-align: right">
                                                <v-subheader>
                                                  <v-menu scale offset-y>
                                                    <template v-slot:activator="{ on, attrs }">
                                                      <v-btn v-bind="attrs" v-on="on" icon @click="picker_selected = child_item.id">
                                                        <v-icon>mdi-emoticon</v-icon>
                                                      </v-btn>
                                                    </template>
                                                    <!--                                                    子评论的回复框的表情选择器-->
                                                    <picker
                                                      style="height: 25vh"
                                                      :include="['people','Smileys']"
                                                      :showSearch="false"
                                                      :showPreview="false"
                                                      :showCategories="false"
                                                      @select="addEmoji"
                                                    />
                                                  </v-menu>
                                                </v-subheader>
                                              </v-col>
                                              <v-col cols="12" lg="2" style="text-align: center">
                                                <v-subheader>
                                                  <v-btn rounded outlined color="grey" width="6vw"
                                                         @click="reply_comment(child_item.id,item.id)">
                                                    <span style="color: #2C2E2D">回复</span>
                                                  </v-btn>
                                                </v-subheader>
                                              </v-col>
                                            </v-row>
                                          </div>
                                        </v-list-item-content>
                                      </v-list-item>
                                    </template>
                                  </v-list>
                                </div>
                              </v-list-item-content>
                            </v-list-item>
                          </template>
                        </v-list>
                        <v-pagination
                          v-if="total!==0&&total!==1"
                          v-model="page"
                          :length="total"
                          @input="change_page(page)"
                          circle
                        ></v-pagination>
                      </v-container>
                    </v-sheet>

js部分:

data: () => ({
    comment_list: [], //评论列表
    comment_count: 0, //总计评论数
    comment_content: '', //评论框输入内容——主评论框
    children_comment_content: '', //回复评论框输入内容(所有评论共享)
    input_length: 200, //评论框剩余可输入字数
    reply_length: 200, //回复框剩余可输入字数
    page: 1, //评论当前页数
    total: 0, //评论总页数
    children_show: 0, //控制子评论列表重新渲染的key
    picker_selected: 'comm', //当前选中的表情选择器的id
    delete_confirm: false, //删除确认对话框
  }),
methods: {
    async get_comment(PageNum) { //获取评论
      await this.checkFollowState()
      request.get("/s-comment/getBySolution",{
        params: {
          PageNum: PageNum,
          PageSize: 5,
          solution_id: this.parseJSONCapture(this.decodeCapture(this.$route.query.solution))
        }
      }).then(res => {
        if (res.code === '200'){
          if (res.data === null){
            this.comment_list = []
            this.comment_count = 0
            this.total = 0
          }
          else {
            this.comment_list = res.data.list
            this.comment_count = res.data.total
            this.total = Math.ceil(res.data.originCount / 5)
            for(let comment of this.comment_list) {
              comment.show_input = false
              if(comment.children.length !== 0) {
                comment.show_children = false
                for(let c of comment.children) {
                  c.show_input = false
                }
              }
            }
            this.children_show += 1
          }
        }
      })
    },
    change_page(pageNum) { //评论翻页
      this.get_comment(pageNum)
    },
    word_limit() { //修改评论编辑框事件——统计和限制字数
      this.comment_content = this.comment_content.substring(0, 200)
      this.input_length = 200 - this.comment_content.length
    },
    reply_word_limit() { //修改回复编辑框事件——统计和限制字数
      this.children_comment_content = this.children_comment_content.substring(0, 200)
      this.reply_length = 200 - this.children_comment_content.length
    },
    show_reply(item) { //点击回复按钮事件
      this.children_comment_content='' //清空回复框内容
      for(let comment of this.comment_list) { //遍历所有评论,设置回复框不可见
        comment.show_input = false
        if(comment.children.length !== 0) {
          for(let c of comment.children) {
            c.show_input = false
          }
        }
      }
      this.picker_selected = item.id //设置当前选中的表情选择器的id
      item.show_input = true //设置当前回复框可见
      this.children_show += 1 //重新渲染
    },
    hide_reply(item) { //收起回复框按钮事件
      item.show_input = false //设置当前回复框不可见
      this.children_show += 1 //重新渲染
    },
    send_comment() { //发布评论
      if(this.comment_content.split('\n').join('').split(' ').join('').length === 0) {
        this.sendWarnMessage('请输入评论内容')
      } else {
        let s_comment = {}
        s_comment.userId = -1
        s_comment.solutionId = this.solutionId
        s_comment.content = this.comment_content
        request.post("/s-comment",s_comment).then(res => {
          if(res.code === '200') {
            this.comment_content = ''
            this.page = 1
            this.get_comment(this.page)
            this.sendSuccessMessage('评论成功')
          }
          else {
            this.sendWarnMessage(res.msg)
            this.get_comment(this.page)
          }
        })
      }
    },
    reply_comment(pid,originId) { //回复评论
      if(this.children_comment_content.split('\n').join('').split(' ').join('').length === 0) {
        this.sendWarnMessage('请输入评论内容')
      } else {
        let s_comment = {}
        s_comment.userId = -1
        s_comment.solutionId = this.solutionId
        s_comment.content = this.children_comment_content
        s_comment.pid = pid
        s_comment.originId = originId
        request.post("/s-comment",s_comment).then(res => {
          if(res.code === '200') {
            this.children_comment_content = ''
            this.get_comment(this.page)
            this.sendSuccessMessage('评论成功')
          } else {
            this.sendWarnMessage('评论失败')
            this.get_comment(this.page)
          }
        })
      }
    },
    addEmoji(emotion){ //添加表情
      if(this.input_length < 2) {
        this.$message.warning("超过最大字数,无法插入表情")
      } else {
        let textarea = document.getElementById(this.picker_selected)
        if (window.getSelection) {
          // 非IE浏览器
          textarea.setRangeText(emotion.native);
          // 在未选中文本的情况下,重新设置光标位置
          textarea.selectionStart += emotion.native.length;
          textarea.focus()
          if(this.picker_selected === 'comm') {
            this.comment_content = textarea.value
          } else {
            this.children_comment_content = textarea.value
          }
        } else if (document.selection) {
          // IE浏览器
          this.comment_content.focus();
          let sel = document.selection.createRange();
          sel.text = emotion.native;
        }
      }
    },
    delete_comment(item,dialog) { //删除评论
      request.delete("/s-comment/"+item.id).then(res => {
        if(res.code==='200') {
          this.sendSuccessMessage('删除评论成功')
          this.get_comment(this.page)
        } else {
          this.sendWarnMessage('删除评论失败')
          this.get_comment(this.page)
        }
      })
      dialog.value = false
    },
    goto_comment() { //滚动到评论区
      this.$vuetify.goTo(this.$refs.comment_area, {
        duration: 500,
        offset: 50,
        easing: 'easeInOutCubic',
      })
    },
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Django中实现评论功能,一般需要以下步骤: 1. 创建Comment模型并与其他模型进行关联,例如某篇文章的评论。 2. 编写CommentForm表单,用于接收用户提交的评论内容。 3. 在视图函数中处理表单数据,验证并保存评论到数据库。 4. 在模板中展示评论列表和评论表单。 下面是一个简单的实现过程: 1. 创建Comment模型 ```python from django.db import models from django.contrib.auth.models import User class Comment(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) content = models.TextField() created_time = models.DateTimeField(auto_now_add=True) article = models.ForeignKey('Article', on_delete=models.CASCADE) def __str__(self): return self.content ``` 2. 编写CommentForm表单 ```python from django import forms class CommentForm(forms.Form): content = forms.CharField(widget=forms.Textarea) ``` 3. 编写视图函数 ```python from django.shortcuts import render, get_object_or_404, redirect from .models import Article, Comment from .forms import CommentForm def article_detail(request, pk): article = get_object_or_404(Article, pk=pk) comments = Comment.objects.filter(article=article) if request.method == 'POST': form = CommentForm(request.POST) if form.is_valid(): comment = form.save(commit=False) comment.user = request.user comment.article = article comment.save() return redirect('article_detail', pk=article.pk) else: form = CommentForm() return render(request, 'article_detail.html', {'article': article, 'comments': comments, 'form': form}) ``` 4. 在模板中展示评论列表和评论表单 ```html {% extends 'base.html' %} {% block content %} <h1>{{ article.title }}</h1> <p>{{ article.content }}</p> <h2>Comments</h2> <ul> {% for comment in comments %} <li>{{ comment.content }}</li> {% empty %} <li>No comments yet.</li> {% endfor %} </ul> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Submit</button> </form> {% endblock %} ``` 以上是一个简单的评论功能实现过程,需要根据具体情况进行调整和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值