13.6 开发消息中心页面
点击头部组件的小铃铛图标,就会进入消息中心页面。该页面展示用户收到的消息列表,包括评论消息、点赞与收藏消息、关注消息三类,可以通过 tab 标签切换查看。
在 tab 标签上还会标记当前未读消息的数量,点击查阅后消息会标记为已读,该功能会在查询消息列表时自动标记。界面如图所示:
(1)创建文件 views/messages/index.vue 表示消息中心页,并添加一条路由配置如下:
js
// router/routes.ts
{
path: '/messages',
name: 'messages',
component: () => import('@/views/messages/index.vue'),
},
(2)编写 tab 标签的模版代码,并根据状态判断某个标签是否被选中,且当有未读消息时展示未读消息的数量,代码如下:
html
<div class="banner-box">
<ul class="fx" @click="onChange">
<li data-val="1" :class="['hover', { active: type == '1' }]">
评论
<el-badge
:value="store.msgInfo.comment"
:hidden="store.msgInfo.comment == 0"
/>
</li>
<li data-val="2" :class="['hover', { active: type == '2' }]">
赞和收藏
<el-badge
:value="store.msgInfo.praise"
:hidden="store.msgInfo.praise == 0"
/>
</li>
<li data-val="3" :class="['hover', { active: type == '3' }]">
新增粉丝
<el-badge
:value="store.msgInfo.follow"
:hidden="store.msgInfo.follow == 0"
/>
</li>
</ul>
</div>
编写上方代码中 tab 标签对应的样式,代码如下:
less
.banner-box {
height: 46px;
background: #fff;
position: fixed;
top: 60px;
left: 0;
right: 0;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
ul {
width: 1200px;
margin: auto;
li {
line-height: 46px;
margin-right: 36px;
font-size: 14px;
.el-badge {
transform: translateY(2px) scale(0.8);
}
}
}
}
(3)在消息 Store 中添加 getComment()、getPraises()、getFollows() 三个方法,分别用户获取评论消息、点赞与收藏消息、关注消息的列表数据,代码如下:
js
{
async getComment(fun: (res: any) => void) {
try {
let res: any = await request.get('/comments/mylist')
if (res) {
fun(res)
}
} catch (error) {
console.log(error)
}
},
async getPraises(fun: (res: any) => void) {
try {
let res: any = await request.get('/praises/mylist')
if (res) {
fun(res)
}
} catch (error) {
console.log(error)
}
},
async getFollows(fun: (res: any) => void) {
try {
let res: any = await request.get('/follows/lists')
if (res) {
fun(res)
}
} catch (error) {
console.log(error)
}
},
}
(4)编写组件的 JS 代码,包含引入 Store、获取 URL 参数、获取各类消息列表的 getMessage()方法,代码如下:
vue
<script setup lang="ts">
import { messageStore, userStore } from "@/stores";
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const store = messageStore();
const type = ref("1");
const comments = ref([]);
const praises = ref([]);
const follows = ref([]);
const getMessage = () => {
if (type.value == "1") {
store.getComment((res) => {
comments.value = res.data;
});
}
if (type.value == "2") {
store.getPraises((res) => {
praises.value = res.data;
});
}
if (type.value == "3") {
store.getFollows((res) => {
follows.value = res.data;
});
}
};
onMounted(() => {
let rtype = route.query.type as string;
if (!rtype) {
type.value = "1";
} else {
type.value = rtype;
}
getMessage();
});
</script>
(5)以评论消息为例,将获取到的评论消息列表数据渲染,并展示出评论的内容、创建者、被评论的文章或沸点的基本信息等,模版代码如下:
html
<div class="msgs-list" v-if="type == '1'">
<div v-for="item in comments" class="msg-item fxt">
<el-avatar :size="45">
<img src="@/assets/avatar.png" />
</el-avatar>
<div class="msg-infos">
<div class="udesc">
<span class="u" @click="toLink(item.created_by, 1)"
>{{ item.user.username }}</span
>
<span
>{{ item.type == 'source' ? '评论了你的' : '回复了你在' }}{{
item.source_type == 1 ? '文章' : '沸点' }}</span
>
<span
v-if="item.source_type == 1"
class="source"
@click="toLink(item.source_id, 2)"
>
{{ item.article.title }}
</span>
<span v-else>沸点</span>
<span v-if="item.type != 'source'">下的评论</span>
</div>
<div class="content">{{ item.content }}</div>
<div class="time">{{ getTimer(item.created_at) }}</div>
</div>
</div>
</div>
编写上方代码中评论列表区域的样式,如下:
less
.msg-item {
background: #fff;
margin-bottom: 10px;
padding: 20px;
position: relative;
.msg-infos {
flex: 1;
margin-left: 22px;
font-size: 15px;
color: var(--font-color3);
.udesc {
margin-bottom: 10px;
.u {
font-weight: 600;
color: #000;
}
.source {
color: var(--el-color-primary);
cursor: pointer;
}
}
.content {
padding: 10px;
background: #f2f3f5;
border: 1px solid #ddd;
margin: 0 20px 10px 0;
}
}
&.border {
margin-bottom: 0;
}
}
(7)在 JS 代码中导入事件处理函数,页面跳转方法等,如下:
js
import { getTimer } from "@/utils";
const { toggleFollow } = userStore();
const toLink = (id: string, tar: 1 | 2) => {
let prex = tar == 1 ? "/user/" : "/article/";
window.open(prex + id);
};
const toFollow = (row: any) => {
let { fans_id } = row;
toggleFollow({ user_id: fans_id }, (res) => {
row.is_follow = !row.is_follow;
});
};
const onChange = (e: MouseEvent) => {
let dom: any = e.target;
if (dom.tagName != "LI") return;
type.value = dom.dataset.val;
if (type.value != "1") {
router.push({
query: { type: type.value },
});
} else {
router.push("/messages");
}
getMessage();
};
关注者列表中有快捷关注按钮,因此要定义 toFollow() 方法快速回关粉丝。