Skip to content

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() 方法快速回关粉丝。

13.6.6