我实现了一个乞丐版的评论功能

news2025/1/24 8:41:35

文章目录

  • 设计评论功能
    • 0 设计初衷
    • 1 前端组建设计
      • **设计原则**
      • **设计代码**
      • 组件核心代码
      • **调用组建并给出mock数据**
      • **效果**
    • 2 后端数据库设计
    • 3 后端接口设计
    • 4 前后端联调
    • 5 后端评论保存接口设计
    • 6 前端评论填写流程设计
    • 7 联调
    • 8 验证码美化

设计评论功能

0 设计初衷

经过长达八个月的更新迭代,文章的内容已经比较丰富,为了达到评论互动的目的,同时秉承能用就行的原则,开发这个评论功能。

那就叫小码吧 已经部署线上。

在这里插入图片描述

1 前端组建设计

设计原则

  • 1 原则1:使用现有element ui 树形组件不重复造轮子
  • 2 原则2:先能用后续完善UI

设计代码

组件核心代码

<template>
  <div class="commentArea">
    <el-tree :data="commentTreeData" :props="defaultProps" @node-click="handleNodeClick" :render-content="renderContent"></el-tree>
  </div>
</template>

<script>
export default {
  name: 'CommnetArea',
  methods:{
    // render-content指定渲染函数,该函数返回需要的节点区内容
    // scoped slot 会传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据
    renderContent(h, { node, data }) {
        return (
          <div class="comment-tree-node">
            {/* <el-avatar shape="square" :size="100" src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-avatar> */}
            <image src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"/>
            <span>{data.userName}{node.label}</span>
            <span>
              <el-button size="mini">回复</el-button>
            </span>
          </div>);
      },
      handleNodeClick(data) {
        console.log(data);
      }
    },
  props:{
    commentTreeData:Array,
    defaultProps:Object
  }  

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

调用组建并给出mock数据

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <CommnetArea :commentTreeData="comdata" :defaultProps="defaultProps"/>
  </div>
</template>

<script>
import CommnetArea from './components/CommnetArea.vue'

export default {
  name: 'App',
  components: {
    CommnetArea
  },
  data() {
      return {
        comdata: [{
          id:200010,
          parentId:0,
          userId: 1001,
          userName: '胡歌',
          avatarSrc: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
          commentContent: '这个文章写的也太好了吧?',
          children: [{
            id:200011,
            parentId:200010,
            userId: 1002,
            userName: '伊芙丽',
            avatarSrc: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
            commentContent: '好吗,也就是入门水平吧!',
            children: [{
              id:200012,
              parentId:200011,
              userId: 1003,
              userName: '曹三星',
              avatarSrc: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
              commentContent: '确实是入门水平但是很有理解。'
            }]
          }]
        }],
        defaultProps: {
          children: 'children',
          label: 'commentContent'
        }
      };
    }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

效果

图片.png

2 后端数据库设计

设计原则:

  • 1 字段见名知义
  • 2 考虑后续扩展
  • 3 适当的字段应加上索引
  • 4 考虑字段存储长度

建表语句

CREATE TABLE MARK_COMMENT (
	ID BIGINT NOT NULL COMMENT '评论ID' PRIMARY KEY,
	OBJ_ID BIGINT NOT NULL COMMENT '评论对象ID(可能是文章、评论或者其他模块的评论对象ID)',
	PARENT_ID BIGINT DEFAULT 0 NOT NULL COMMENT '父级ID,顶级为0',
	USER_ID BIGINT NOT NULL COMMENT '用户ID',
	USER_NAME varchar(255) NULL COMMENT '用户名称',
	AVATAR_SRC varchar(255) NOT NULL COMMENT '用户头像',
	COMMENT_TIME DATETIME NOT NULL COMMENT '评论时间',
	COMMENT_CONTENT varchar(500) NOT NULL COMMENT '评论内容'
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci
COMMENT='评论表';

ALTER TABLE  MARK_COMMENT ADD INDEX IDX_MARKCOMMENT_OBJ_ID(OBJ_ID);
ALTER TABLE  MARK_COMMENT ADD INDEX IDX_MARKCOMMENT_PARENT_ID(PARENT_ID);
ALTER TABLE  MARK_COMMENT ADD INDEX IDX_MARKCOMMENT_USER_ID(USER_ID);


INSERT INTO `goods_mark`.`MARK_COMMENT` (`ID`, `OBJ_ID`, `PARENT_ID`, `USER_ID`, `USER_NAME`, `AVATAR_SRC`, `COMMENT_TIME`, `COMMENT_CONTENT`) VALUES (200010, 1597083492114546688, 0, 1001, '胡歌', 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', '2023-04-20 22:18:18', '这个文章写的也太好了吧?');
INSERT INTO `goods_mark`.`MARK_COMMENT` (`ID`, `OBJ_ID`, `PARENT_ID`, `USER_ID`, `USER_NAME`, `AVATAR_SRC`, `COMMENT_TIME`, `COMMENT_CONTENT`) VALUES (200011, 1597083492114546688, 200010, 200010, '伊芙丽', 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', '2023-04-14 22:19:25', '好吗,也就是入门水平吧!');
INSERT INTO `goods_mark`.`MARK_COMMENT` (`ID`, `OBJ_ID`, `PARENT_ID`, `USER_ID`, `USER_NAME`, `AVATAR_SRC`, `COMMENT_TIME`, `COMMENT_CONTENT`) VALUES (200012, 1597083492114546688, 200011, 200011, '曹三星', 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', '2023-04-13 22:20:17', '确实是入门水平但是很有理解。');

3 后端接口设计

设计原则:

  • 1 返回属性字段见名知义
  • 2 不返回无用属性
    接口返回值:
GET http://localhost:8088/xxxx/xxxxxxxx?xxxxxxx=1323123432

HTTP/1.1 200 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 15 Apr 2023 07:59:57 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "status": 200,
  "message": "获取评论列表成功!",
  "stackTrace": null,
  "data": {
    "result": [
      {
        "id": "200010",
        "parentId": "0",
        "userId": 1001,
        "userName": "胡歌",
        "avatarSrc": "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
        "commentContent": "这个文章写的也太好了吧?",
        "children": [
          {
            "id": "200011",
            "parentId": "200010",
            "userId": 200010,
            "userName": "伊芙丽",
            "avatarSrc": "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
            "commentContent": "好吗,也就是入门水平吧!",
            "children": [
              {
                "id": "200012",
                "parentId": "200011",
                "userId": 200011,
                "userName": "曹三星",
                "avatarSrc": "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
                "commentContent": "确实是入门水平但是很有理解。",
                "children": null
              }
            ]
          }
        ]
      }
    ]
  }
}

Response code: 200; Time: 406ms; Content length: 671 bytes

4 前后端联调

接口请求
这里直接从路由中拿到文章ID,直接请求接口即可

    initCommentTree() {
      let that = this;
      api_getCommentByArticleId(that.$route.params.articleId).then(resp => {
        if (resp.data.status==200) {
          that.commentData = resp.data.data.result;
        } else {
          that.$message({message: resp.data.data.message, type: 'error', showClose: true})
        }
      });
    }

联调结果
image.png

剩下按照同样的步骤实现文章的评论功能

5 后端评论保存接口设计

评论文章

{
  "objIdString": "MTYyMzI5MjMzNTIwMjMyODU3Ng==",
  "parentId": 0,
  "userId": 59,
  "userName": "王志利",
  "avatarSrc": "123.jpg",
  "commentContent": "测试接口新增评论,评论rabbitMQ"
}

评论评论

{
  "objIdString": "MTYyMzI5MjMzNTIwMjMyODU3Ng==",
  "parentId": 0,
  "userId": 59,
  "userName": "王志利",
  "avatarSrc": "123.jpg",
  "commentContent": "测试接口新增评论,评论rabbitMQ"
}

image.png

6 前端评论填写流程设计

用户输入昵称,邮箱,获取验证码----》输入验证码-----》提交编写的评论
验证码,以及邮箱给出合理教研

7 联调

联调结果
image.png

8 验证码美化

这里从网上找到一个很不错的响应式模板可以拿来使用。

<html lang="">
<meta charset="utf-8">
<body>
<div id="contentDiv" onmouseover="getTop().stopPropagation(event);"
     onclick="getTop().preSwapLink(event, 'html', 'ZC0004_vDfNJayMtMUuKGIAzzsWvc8');"
     style="position:relative;font-size:14px;height:auto;padding:15px 15px 10px 15px;z-index:1;zoom:1;line-height:1.7;"
     class="body">
    <div id="qm_con_body">
        <div id="mailContentContainer" class="qmbox qm_con_body_content qqmail_webmail_only" style="opacity: 1;">
            <style type="text/css">
        .qmbox h1,.qmbox 			h2,.qmbox 			h3 {				color: #e11e1e;			}			.qmbox p {				padding: 0;				margin: 0;				color: #333;				font-size: 16px;			}			.qmbox hr {				background-color: #d9d9d9;				border: none;				height: 1px;			}			.qmbox .eo-link {				color: #0576b9;				text-decoration: none;				cursor: pointer;			}			.qmbox .eo-link:hover {				color: #3498db;			}			.qmbox .eo-link:hover {				text-decoration: underline;			}			.qmbox .eo-p-link {				display: block;				margin-top: 20px;				color: #009cff;				text-decoration: underline;			}			.qmbox .p-intro {				padding: 30px;			}			.qmbox .p-code {				padding: 0 30px 0 30px;			}			.qmbox .p-news {				padding: 0px 30px 30px 30px;			}

            </style>
            <div style="max-width:800px;padding-bottom:10px;margin:20px auto 0 auto;">
                <table cellpadding="0" cellspacing="0"
                       style="background-color: #fff;border-collapse: collapse; border:1px solid #e5e5e5;box-shadow: 0 10px 15px rgba(0, 0, 0, 0.05);text-align: left;width: 100%;font-size: 14px;border-spacing: 0;">
                    <tbody>
                    <tr style="background-color: #f8f8f8;">
                        <td>
                            <img style="padding: 15px 0 15px 30px;width:50px"
                                 src="https://s3.bmp.ovh/imgs/2023/02/03/62d56eb6b3034807.jpg"> <span> 集美小窝. </span>
                        </td>
                    </tr>
                    <tr>
                        <td class="p-intro">
                            <h1 style="font-size: 26px; font-weight: bold;">验证您的邮箱地址</h1>
                            <p style="line-height:1.75em;">感谢您使用 集美小窝. </p>
                            <p style="line-height:1.75em;">若非本人操作请忽视此信息</p>
                            <p style="line-height:1.75em;">以下是您的邮箱验证码,请将它输入到 集美小窝 的邮箱验证码输入框中:</p>
                        </td>
                    </tr>
                    <tr>
                        <td class="p-code">
                            <p style="color: #253858;text-align:center;line-height:1.75em;background-color: #f2f2f2;min-width: 200px;margin: 0 auto;font-size: 28px;border-radius: 5px;border: 1px solid #d9d9d9;font-weight: bold;">
                                10010086 </p>
                        </td>
                    </tr>
                    <tr>
                        <td class="p-intro">
                            <p style="line-height:1.75em;">这一封邮件包括一些您的 集美小窝
                                账号信息,请不要回复或转发它,以免带来不必要的信息泄露风险。 </p>
                        </td>
                    </tr>
                    <tr>
                        <td class="p-intro">
                            <hr>
                            <p style="text-align: center;line-height:1.75em;"> 集美小窝</p>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>
            <style type="text/css">
        .qmbox style, .qmbox script, .qmbox head, .qmbox link, .qmbox meta {display: none !important;}

            </style>
        </div>
    </div><!-- -->
    <style>
    #mailContentContainer .txt {height:auto;}

    </style>
</div>
</body>
</html>

实现效果
::: hljs-center

在这里插入图片描述

:::

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/433848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三百左右的蓝牙耳机哪个音质好?三百左右音质最好的蓝牙耳机推荐

在外出携带的数码产品中&#xff0c;蓝牙耳机的出现频率居高不下&#xff0c;一部手机&#xff0c;一副耳机已经成为不少人外出的标配。蓝牙耳机无外乎是用来听的&#xff0c;下面&#xff0c;我来给大家推荐几款三百左右音质好的蓝牙耳机&#xff0c;一起来看看吧。 一、南卡…

LabVIEW-字符串与路径控件

在前面板中字符串与路径控件位于下图所示位置&#xff1a; 字符串输入和显示功能&#xff0c;是用户最常用的基本操作功能单击字符串控件&#xff0c;鼠标右键&#xff0c;选择“属性”可以对字符串控件的外观进行设置。显示样式有四种方式&#xff0c;即正常、反斜杠符号、密码…

家用洗地机好用吗?好用的洗地机分享

洗地机是一种高效、节能、环保的清洁设备&#xff0c;广泛应用于各种场所的地面清洁工作。它不仅可以快速清洁地面&#xff0c;还可以有效去除污渍、油渍等难以清洁的污染物&#xff0c;让地面恢复光洁如新的状态。同时&#xff0c;洗地机还可以减少清洁人员的劳动强度&#xf…

研读Rust圣经解析——Rust learn-10(泛型,trait,生命周期)

研读Rust圣经解析——Rust learn-10&#xff08;泛型&#xff0c;trait&#xff0c;生命周期&#xff09; 泛型应用泛型方法泛型结构体枚举泛型方法定义中的泛型 trait定义一个trait默认trait方法实现为结构体实现trait调用trait中实现的方法将trait作为参数trait bound多实现入…

2023年6月CDGP数据治理专家认证考试火热报名中

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

数据结构—单链表

目录 1.前言 2.了解单链表 3.单链表代码实现 3.1 单链表结构体实现 3.2 创建节点 3.3 打印单链表 3.4 尾插 3.5 头插 3. 6 头删 3.7 尾删 3.8 查找 3.9 插入 3.9.1 在pos位置之前插入 3.9.2 在pos位置之后插入&#xff08;主要使用这种功能&#xff09;---不需要找…

家用洗地机到底好不好用?家用洗地机分享

在当今社会&#xff0c;人们越来越关注卫生和清洁&#xff0c;这也促进了家庭和工作场所对清洁设备的需求。洗地机就是其中之一&#xff0c;它的高效和便捷性为我们提供了清洁和保洁的重要帮助。使用洗地机不仅能够卫生地保持地面清洁&#xff0c;而且可以节省时间和人力成本。…

拼多多的天天618,如何掀开电商营销的“皇帝新衣”?

电商价格战如火如荼&#xff0c;拼多多也在2023年4月正式启动“数码家电消费季”百亿补贴。 首季将在百亿补贴的基础上加码10亿&#xff0c;对手机、平板等各种数码家电&#xff0c;提供全品类补贴&#xff0c;苹果、华为、小米、美的等国内外各大品牌均会参与。拼多多相关负责…

安装虚拟机VMshare

前言&#xff1a;虚拟机必须在开机的状态下&#xff0c;而且互相需ping通&#xff0c;mobax才可以连接成功 一、下载VMsharePro软件 1、双击 安装程序&#xff1b; 2、按照步骤 点击一个个的“下一步” 3、安装完成之后&#xff0c;会要求你 输入许可证&#xff0c;这个可以…

【Redis】Redis十大数据类型—字符串String

介绍 获取命令地址 英文&#xff1a;https://redis.io/commands/ 中文&#xff1a;http://www.redis.cn/commands.html 字符串(string) 字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的&#xff0c;这意味着一个Redis字符串能包含任意类型的数据&#xff0c;例…

STM:基于Siamese编码器的时空混频器用于CT扫描肺结节生长趋势预测

文章目录 Siamese Encoder-based Spatial-Temporal Mixer for Growth Trend Prediction of Lung Nodules on CT Scans摘要方法Spatial-Temporal MixerTwo-Layer H-Loss 实验结果 Siamese Encoder-based Spatial-Temporal Mixer for Growth Trend Prediction of Lung Nodules on…

JavaScript的三座大山

前言&#xff1a;这个题目是抄的&#xff0c;看着很有意思&#xff0c;就拿过用了&#xff0c;毕竟CV是程序员的基本功底嘛&#xff0c;顺带把图也拿过来了 作用域和闭包 这个几乎是天天在用的东西&#xff0c;可能有些人甚至不知道这个概念&#xff0c;但是用到过这种方法去解…

Dubbo消费者调用流程分析

消费者在发起一次调用的时候时序图如下 由于Dubbo调用是基于动态代理的方式,所以请求先进入 InvokerInvocationHandler#invoke()方法,进而调用到MockClusterInvoker#invoke()方法。MockClusterInvoker#invoke()中判断是否需要开启 Mock,如果开启 Mock 调用 doMockInvoke 执行…

WebRTC系列-Qos系列之AEC-可配置参数

文章目录 1. 简介2. 源码中相关参数WebRTC的自适应回声消除(AEC)是一个广泛使用的技术,用于在音频通信中消除扬声器输出产生的回声。在WebRTC中,有三种AEC算法可供选择,分别是 AECM、 AEC和 AEC3。本文将介绍WebRTC AEC 3算法的原理和应用场景。 在上图中可以看出AEC算…

MiniGPT4,开源了。

大家好&#xff0c;我是 Jack。 一个月前&#xff0c;我发布过一篇文章&#xff0c;讲解了 GPT4 的发布会。 ChatGPT 的对话能力&#xff0c;想必大家也早已体验过了&#xff0c;无论是文本生成能力&#xff0c;还是写代码的能力&#xff0c;甚至是上下文的关联对话能力&#…

SpringBoot自定义登录、权限验证

1、首先最基础的User实体类&#xff0c;使用了lombok&#xff0c;所以省略了getter、setter方法 Data public class UserInfo implements Serializable {private Integer id;//用户名private String username;//密码不需要被序列化存入redisprivate transient String password…

vue3类型uniapp调用signalr

目录 背景 安装 renderjs 1选择一个tab页面承载renderjs代码 2编写业务逻辑代码 3编写renderjs代码 背景 后端使用.net6开发&#xff0c;长链接选择了微软的signalr而非原生的websocket 前端uniapp下vue3类型开发的app&#xff0c;需要通过长链接获取后端推送的消息 安…

通过对话了解cookie session与token的用途和区别

1 先来了解cookie与localstorage 1.1 http的无状态 用户: 我想看csdn我有多少粉丝了(http请求) 服务器:你是&#xff1f;请告诉我你的名字和密码&#xff0c;我确认你是谁 用户&#xff1a;发起登录请求 admin 123456 服务器&#xff1a;ok&#xff0c;登录成功 用户&…

分享几个国内免费的ChatGPT镜像网址(亲测有效)

最近由于ChatGPT的爆火也让很多小伙伴想去感受一下ChatGPT的魅力&#xff0c;那么今天就分享几个ChatGPT国内的镜像网址&#xff0c;大家可以直接使用&#xff01;记得点赞收藏一下呦&#xff01; 1、AQ Bot&#xff0c;网址&#xff1a;点我 https://su.askaiw.com/aq 缺点&…

搭建CDH流程记录

搭建CDH流程记录 如何搭建本地yum源 1.配置yum源这里使用 阿里源 http://mirrors.aliyun.com/repo/Centos-7.repo wget http://mirrors.aliyun.com/repo/Centos-7.repo2.安装http软件 yum install httpd -y3.配置httpd.conf vi /etc/httpd/conf/httpd.conf在 AddType appli…