创新设计记录-8:博客收藏
按照大部分app对收藏的实现,效果应该是在论坛上在看某个博客时,发现博客非常值得品鉴,值得收藏,那么就会在博客的下边点击收藏按钮,就可以添加到用户自己的收藏夹了。
后端接口
def star_unstar_blog(user_id: str, blog_id: str) -> BaseResponse:
"""收藏一个博客,或者取消收藏一个博客"""
try:
with Session(engine) as session:
res = session.query(BlogStars).filter(BlogStars.user_id == user_id).filter(
BlogStars.blog_id == blog_id).first()
if res is None:
session.add(BlogStars(user_id=user_id, blog_id=blog_id))
session.commit()
return BaseResponse(code=200, msg='收藏成功', data=True)
else:
session.delete(res)
session.commit()
return BaseResponse(code=200, msg='取消收藏', data=False)
except Exception as e:
print(e)
return BaseResponse(code=500, msg=str(e))
这个接口集收藏/取消收藏于一身。
我们的收藏记录存放在一个叫StarBlogs的多对多的表中,收藏时将收藏者的用户id和要收藏的博客id发送到后端,后端查询,如果数据库中没有这一条记录,证明是收藏操作,如果能查到这条记录,则证明是取消收藏操作。
def get_star_blog(user_id: str) -> BaseResponse:
try:
with (Session(engine) as session):
res = session.query(BlogStars, Blog, User).join(Blog, Blog.id == BlogStars.blog_id).join(User, User.id == Blog.user_id).filter(
BlogStars.user_id == user_id).all()
s_res = [serialize_stars_blog(i) for i in res]
for blog in s_res:
blog.update({"is_starred": True})
return BaseResponse(code=200, msg='ok', data={'star_blog_list': s_res})
except Exception as e:
print(e)
return BaseResponse(code=500, msg=str(e))
这个接口用来获取用户的收藏夹中的博客,为了前端便于显示,在列表中添加is_starred
标志位,前端如果是已经收藏的博客,就会显示已收藏
防止用户误解或者忘记是否已经收藏。
在论坛中的get_all_blogs中也有类似的操作
...
for blog in res_data:
stmt = exists().where(BlogStars.blog_id == blog['id'],
BlogStars.user_id == login_user_id)
is_starred = session.query(stmt).scalar()
blog.update({"is_starred": is_starred})
...
这样不管从收藏夹中查看博客还是从论坛中查看博客,都有正确的人性化的状态显示。
前端:
收藏夹:
前端在收藏夹/博客页面从后端获取到博客列表之后,从数据中获取is_starred
字段,传给子组件BlogCard
<template>
<el-card shadow="hover" body-class="card-body" class="blog-card" style="">
<div class="header">
<h3>
<el-link :href=url style="font-size: 25px; font-weight: bold;">
{{ blog_title }}
</el-link>
</h3>
</div>
<div class="body">
<el-text line-clamp="2" truncated>
{{ blog_content }}
</el-text>
</div>
<div style="text-align: end">作者:{{ blog_author }}</div>
</el-card>
</template>
<script>
export default {
name: 'forum',
props: {
blog_id: String,
blog_title: String,
blog_author: String,
blog_content: String,
is_starred: Boolean
},
computed: {
url() {
return '/forum_blog?blog_id=' + this.blog_id + '&author=' + this.blog_author + '&is_starred=' + this.is_starred
}
}
}
</script>
上面的is_starred
属性可以判断博客是否已经被收藏,点击标题的时候被路由到博客界面,就可以对应显示不同的按钮
<el-button type="warning" v-if="this.is_starred" @click="_star_unstar_blog()">
<el-icon size="20">
<StarFilled />
</el-icon>
已收藏</el-button>
<el-button type="warning" v-if="!this.is_starred" @click="_star_unstar_blog()">
<el-icon size="20">
<Star />
</el-icon>
收藏</el-button>
<script>
...
created(){
this.is_starred = this.$route.query.is_starred == 'true' ? true : false
}
...
</script>
收藏功能就已经实现