我实现了一个乞丐版的评论功能
文章目录
设计评论功能
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>
效果
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=1323123432HTTP/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})}});}
联调结果
剩下按照同样的步骤实现文章的评论功能
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"
}
6 前端评论填写流程设计
用户输入昵称,邮箱,获取验证码----》输入验证码-----》提交编写的评论
验证码,以及邮箱给出合理教研
7 联调
联调结果
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
:::