#头条创作挑战赛#
本文同步本人掘金平台的文章:https://juejin.cn/post/6982713711584608270
留言功能在社交中占据很重要的作用。这里实现的留言功能,参考微信朋友圈的方式:
用户发送一个TOPIC话题,读者可以在该话题下面进行评论,也可以对该话题下的留言进行评论。但是始终只会展示两层树的评论。
当然,也可以像掘金这样进行嵌套多层树的结构展示。臣妾觉得嵌套得太深~
实际完成的效果如下:
体验站点请戳 jimmyarea.com 。
使用技术
在上面的截图中,很明显,就是一个表单的设计,外加一个列表的展示。
表单的设计使用了ant design框架自带的form组件:
复制代码
这里限制了输入的主题名称的长度为6-30;内容是30-300字符
针对留言的展示,这里使用的是ant design自带的List和Comment组件:
`共 ${count} 条`,
pageSize,
current: activePage,
onChange: changePage,
}}
dataSource={list}
renderItem={(item: any, index: any) => (
}
title={{item.subject}}
description={
<>
{item.content}
{/* 子留言 */}
用户 {item.userId?.username} 发表于
{moment(item.meta?.createAt).format('YYYY-MM-DD HH:mm:ss')}
{item.canDel ? (
removeMsg(item)}
>
Delete
) : null}
replyMsg(item)}
>
Reply
{/* 回复的内容 */}
{item.children && item.children.length ? (
<>
{item.children.map((innerItem: any, innerIndex: any) => (
{innerItem.subject}}
avatar={
{innerItem.userId?.username?.slice(0, 1)?.toUpperCase()}
}
content={{innerItem.content}
}
datetime={
{moment(innerItem.meta?.createAt).fromNow()}
}
actions={[
<>
{innerItem.canDel ? (
removeMsg(innerItem)}
>
Delete
) : null}
>,
replyMsg(innerItem)}
>
Reply
,
]}
/>
))}
>
) : null}
{/* 回复的表单 */}
{replyObj._id === item._id || replyObj.pid === item._id ? (
) : null}
>
}
/>
)}
/>
复制代码
当然,如果是多级地树结构嵌套,你完全可以只是使用Comment组件进行递归调用
列表是对用户发表的主题,留言以及子留言的展示。如果你纵览上面的代码片段,你会发现里面有一个Form表单。
是的,其Form表单就是给留言使用的,其结构仅仅是剔除了主题留言中的subject字段输入框,但是实际传参我还是会使用到。
完整的前端代码可前往jimmyarea 留言(前端)查看。
使用的技术:
这里的搭建就不进行介绍了,可以参考koa2官网配合百度解决~
其实,本质上还是增删改查的操作。
首先,我们对自己要存储的数据结构schema进行相关的定义:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
// 定义留言字段
let MessageSchema = new Schema({
// 关联字段 -- 用户的id
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
type: Number, // 1是留言,2是回复
subject: String, // 留言主题
content: String, // 留言内容
pid: { // 父id
type: String,
default: '-1'
},
replyTargetId: { // 回复目标记录id, 和父pid有所不同
type: String,
default: '-1'
},
meta: {
createAt: {
type: Date,
default: Date.now()
},
updateAt: {
type: Date,
default: Date.now()
}
}
})
mongoose.model('Message', MessageSchema)
复制代码
这里有个注意的点userId字段,这里我直接关联了注册的用户。
完成了字段的设定之后,下面就可以进行增删改查了。
详细的crud代码可以到jimmyarea 留言(后端) 查看。
本篇的重点是,对评论的话题和留言,如何转换成两层的树型结构呢?
这就是涉及到了pid这个字段,也就是父节点的id: 话题的pid为-1,话题下留言的pid为话题的记录值。如下代码:
let count = await Message.count({pid: '-1'})
let data = await Message.find({pid: '-1'})
.skip((current-1) * pageSize)
.limit(pageSize)
.sort({ 'meta.createAt': -1})
.populate({
path: 'userId',
select: 'username _id' // select: 'username -_id' -_id 是排除_id
})
.lean(true) // 添加lean变成js的json字符串
const pids = Array.isArray(data) ? data.map(i => i._id) : [];
let resReply = []
if(pids.length) {
resReply = await Message.find({pid: {$in: pids}})
.sort({ 'meta.createAt': 1})
.populate({
path: 'userId',
select: 'username _id' // select: 'username -_id' -_id 是排除_id
})
}
const list = data.map(item => {
const children = JSON.parse(JSON.stringify(resReply.filter(i => i.pid === item._id.toString()))) // 引用问题
const tranformChildren = children.map(innerItem => ({
...innerItem,
canDel: innerItem.userId && innerItem.userId._id.toString() === (user._id&&user._id.toString()) ? 1 : 0
}))
return {
...item,
children: tranformChildren,
canDel: item.userId && item.userId._id.toString() === (user._id&&user._id.toString()) ? 1 : 0
}
})
if(list) {
ctx.body = {
results: list,
current: 1,
count
}
return
}
ctx.body = {
code: 10002,
msg: '获取留言失败!'
}
复制代码
至此,可以愉快地进行留言~
页面更新:2024-03-11
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号