Skip to content

Commit

Permalink
feat: 消息通知
Browse files Browse the repository at this point in the history
  • Loading branch information
Fengjing95 committed Oct 4, 2022
1 parent 2464275 commit 80e1d32
Show file tree
Hide file tree
Showing 16 changed files with 662 additions and 19 deletions.
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NODE_ENV = 'development'
VITE_SOCKET_ROOM = 'http://127.0.0.1:7001/room'
VITE_SOCKET_NOTICE = 'http://127.0.0.1:7001/notice'
VITE_HTTP_BASE = 'http://127.0.0.1:7001/api/v1/'
VITE_ANCHOR_DEFAULT_AVATAR = 'https://picgo-1259000609.cos.ap-shanghai.myqcloud.com/picgo/[email protected]'
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NODE_ENV = 'production'
VITE_SOCKET_ROOM = 'http://127.0.0.1:7001/room'
VITE_SOCKET_NOTICE = 'http://127.0.0.1:7001/notice'
VITE_ANCHOR_DEFAULT_AVATAR = 'https://picgo-1259000609.cos.ap-shanghai.myqcloud.com/picgo/[email protected]'
5 changes: 5 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import '@vue/runtime-core'
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AAvatar: typeof import('@arco-design/web-vue')['Avatar']
ABackTop: typeof import('@arco-design/web-vue')['BackTop']
ABadge: typeof import('@arco-design/web-vue')['Badge']
AButton: typeof import('@arco-design/web-vue')['Button']
ACard: typeof import('@arco-design/web-vue')['Card']
ACardMeta: typeof import('@arco-design/web-vue')['CardMeta']
Expand Down Expand Up @@ -33,6 +35,9 @@ declare module '@vue/runtime-core' {
ASkeletonLine: typeof import('@arco-design/web-vue')['SkeletonLine']
ASkeletonShape: typeof import('@arco-design/web-vue')['SkeletonShape']
ASpace: typeof import('@arco-design/web-vue')['Space']
ASubMenu: typeof import('@arco-design/web-vue')['SubMenu']
ATabPane: typeof import('@arco-design/web-vue')['TabPane']
ATabs: typeof import('@arco-design/web-vue')['Tabs']
ATextarea: typeof import('@arco-design/web-vue')['Textarea']
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
ATypographyText: typeof import('@arco-design/web-vue')['TypographyText']
Expand Down
101 changes: 88 additions & 13 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
* @Author: 枫
* @LastEditors: 枫
* @description: description
* @LastEditTime: 2022-09-18 21:49:49
* @LastEditTime: 2022-10-04 10:22:18
-->
<script setup lang="ts">
import { RouterView, useRouter } from "vue-router";
import { useGlobalStore } from "./stores/global";
import { useUserStore } from "./stores/user";
import LoginModal from "./components/login/LoginModal.vue";
import { useNoticeStore } from "./stores/notice";
import { afterLogin } from "./mixins/actionAfterLogin";
import SharedWorker from "./workers/noticeSharedWorker?sharedworker";
import { provide, ref } from "vue";
import { IconNotification } from "@arco-design/web-vue/es/icon";
// import { request } from "./utils/request";

const router = useRouter();
Expand All @@ -20,7 +25,49 @@ const user = useUserStore();
if (!user.token) {
user.getUserInfo();
}
// request.post("/anchor/streamKey").catch((res) => {

const port = ref<MessagePort>();
provide("noticeWorker", port);

function initNoticeWorker() {
const worker = new SharedWorker();
port.value = worker.port;

// 注入到全局

worker.port.start();
worker.port.addEventListener("message", (e) => {
switch (e.data.event) {
// 连接到 sharedworker 时, 目前没有操作
case "connected":
worker?.port.postMessage({ event: "init", payload: user.token });
break;

// 全部已读
// TODO 触发已读的事件发送请求, 保存到本地, 共享事件
case "readAll":
notice.readAll();
break;

// 根据 ID 已读某条消息
case "read":
notice.readNoticeById(e.data.payload);
break;

// 新消息
case "newNotice":
notice.insertNoticeAtHead(e.data.payload);
break;
}
});
}

const notice = useNoticeStore();
afterLogin(() => {
notice.getNotice();
initNoticeWorker();
});
// request.post("/anchor/streamKey") .catch((res) => {
// console.log(res);
// });
// request.get("/user/myInfo").catch((res) => {
Expand Down Expand Up @@ -58,22 +105,42 @@ if (!user.token) {
</template>
</a-menu-item>
</a-menu>

<div class="user-toolbar">
<!-- 动态渲染用户头像或者登录按钮 -->
<div class="login-toolbar" v-if="user.info?.userId">
<div class="user-avatar-action">
<a-avatar class="user-avatar">
<img alt="avatar" :src="user.info?.avatar" />
</a-avatar>

<!-- TODO 用户面板 hover -->
<div class="user-panel">1</div>
<template v-if="user.info?.userId">
<div class="login-toolbar">
<div class="user-avatar-action">
<a-avatar class="user-avatar">
<img alt="avatar" :src="user.info?.avatar" />
</a-avatar>

<!-- TODO 用户面板 hover -->
<div class="user-panel">1</div>
</div>
</div>

<!-- TODO 历史观看 -->
<!-- 消息通知 -->
<div class="action">
<a-badge
:offset="[2, -2]"
:count="notice.notReadNumber"
:max-count="99"
:dotStyle="{
height: '15px',
lineHeight: '15px',
}"
>
<icon-notification
:size="26"
@click="router.push('/member/notice')"
/>
</a-badge>
</div>
</div>
</template>

<span class="unlogin" v-else @click="global.startLogin">&nbsp;</span>
<!-- TODO 历史观看 -->
<!-- TODO 消息通知 -->
</div>
</div>
</div>
Expand Down Expand Up @@ -129,6 +196,7 @@ img {
.login-toolbar {
display: flex;
align-items: center;
margin-right: 30px;

.user-avatar-action {
position: relative;
Expand Down Expand Up @@ -177,6 +245,13 @@ img {
-webkit-background-size: auto 100%;
-webkit-animation: unloginAnimate 1s steps(1) infinite;
}

.action {
cursor: pointer;
// &:hover {
// transform: translateY(-5px);
// }
}
}
}
}
Expand Down
File renamed without changes.
35 changes: 34 additions & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@
* @Author: 枫
* @LastEditors: 枫
* @description: description
* @LastEditTime: 2022-09-21 11:41:08
* @LastEditTime: 2022-10-04 10:02:11
*/
import { createRouter, createWebHistory } from "vue-router";
import { IconNotification, IconUser } from "@arco-design/web-vue/es/icon";
import type { Component } from "vue";

declare module "vue-router" {
interface RouteMeta {
menuName?: string;
needLogin?: boolean;
key?: string;
icon?: Component;
name?: string;
}
}

Expand Down Expand Up @@ -94,6 +99,34 @@ const router = createRouter({
component: () => import("../views/LiveRoom/LiveRoom.vue"),
props: (route) => ({ roomId: route.params.roomId }),
},
{
path: "/member",
name: "member",
component: () => import("../views/MemberCenter/MemberCenter.vue"),
children: [
{
path: "information",
name: "memberInformation",
component: () => import("../views/MemberCenter/MemberNotice.vue"),
meta: {
name: "个人资料",
icon: IconUser,
key: "information",
},
},
{
path: "notice",
name: "memberNotice",
component: () => import("../views/MemberCenter/MemberNotice.vue"),
// props: (route) => ({ active: route.query.active || "thumb" }),
meta: {
name: "消息通知",
icon: IconNotification,
key: "notice",
},
},
],
},
],
});

Expand Down
51 changes: 51 additions & 0 deletions src/services/member.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* @Date: 2022-09-25 21:48:02
* @Author: 枫
* @LastEditors: 枫
* @description: 个人中心接口层
* @LastEditTime: 2022-10-04 13:12:34
*/

import { request } from "@/utils/request";
import type { NoticeDTO } from "#/notice";
import type { PaginationResponseData } from "#/util";

/*
* notice 通知相关
*/

/**
* 获取未读消息
* @returns
*/
export async function getNewNotice(): Promise<NoticeDTO[]> {
return request.get("/message/list");
}

/**
* 获取读取的消息
* @param page 页码
* @returns
*/
export async function getOldNotice(
page: number
): Promise<PaginationResponseData<NoticeDTO>> {
return request.get(`/message/list/read?page=${page}`);
}

/**
* 已读消息
* @param id 消息 ID
* @returns
*/
export async function readNotice(id: number): Promise<boolean> {
return request.put(`/message/read/${id}`);
}

/**
* 全部已读
* @returns
*/
export async function readAllNotice(): Promise<boolean> {
return request.put(`/message/read/all`);
}
72 changes: 72 additions & 0 deletions src/stores/notice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* @Date: 2022-09-25 21:24:05
* @Author: 枫
* @LastEditors: 枫
* @description: 消息通知 store
* @LastEditTime: 2022-10-04 20:31:04
*/

import type { NoticeDTO } from "#/notice";
import { defineStore } from "pinia";
import { getNewNotice, getOldNotice } from "@/services/member";

export const useNoticeStore = defineStore({
id: "notice",
state: () => ({
newNotice: [] as NoticeDTO[],
notice: [] as NoticeDTO[],
page: 1,
loading: false,
total: 0,
}),
actions: {
// 从服务器获取未读消息
async getNotice() {
this.loading = true;
this.newNotice = await getNewNotice();
this.loading = false;
},
async getOldNotice() {
this.loading = true;
const notice = await getOldNotice(this.page);
this.total = notice.total;
this.notice = notice.content;
this.loading = false;
},
// 插入新消息
insertNoticeAtHead(notice: NoticeDTO) {
this.newNotice.unshift(notice);
},
// 已读某条消息
readNoticeById(id: number) {
// const success = await readNotice(id);
// if (success) {
const idx = this.newNotice.findIndex((i) => i.messageId === id);
this.newNotice.splice(idx, 1);
// }
},
// 全部已读
readAll() {
// const success = await readAllNotice();
// if (success)
this.newNotice = [];
},
// 设置页码
setPage(page: number) {
this.page = page;
},
},
getters: {
// 未读消息数
notReadNumber(): number {
return this.newNotice.length;
},
// 已读消息数
readNoticeNumber(): number {
return this.notice.length;
},
isAllLoad(): boolean {
return this.total === this.notice.length;
},
},
});
4 changes: 2 additions & 2 deletions src/views/Favorites/FavoriteList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ RoomDTO
* @Author: 枫
* @LastEditors: 枫
* @description: description
* @LastEditTime: 2022-06-28 19:50:53
* @LastEditTime: 2022-09-27 09:12:50
-->
<template>
<div :style="{ paddingTop: '20px' }">
Expand All @@ -30,7 +30,7 @@ RoomDTO
import { getFavoriteList } from "@/services/favorite";
import { reactive } from "vue";
import RoomCard from "@/components/RoomCard.vue";
import { afterLogin } from "@/utils/actionAfterLogin";
import { afterLogin } from "@/mixins/actionAfterLogin";
import { IconEmpty } from "@arco-design/web-vue/es/icon";
import type { RoomInfoDTO } from "#/room";
// TODO 分页
Expand Down
4 changes: 2 additions & 2 deletions src/views/LiveRoom/LiveRoom.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @Author: 枫
* @LastEditors: 枫
* @description: description
* @LastEditTime: 2022-07-05 10:49:57
* @LastEditTime: 2022-09-27 09:12:47
-->
<template>
<anchor-tool v-if="isAnchor" />
Expand Down Expand Up @@ -43,7 +43,7 @@ import {
} from "@/services/room";
import { io } from "socket.io-client";
import { computed, onMounted, onUnmounted, reactive, ref } from "vue";
import { afterLogin } from "@/utils/actionAfterLogin";
import { afterLogin } from "@/mixins/actionAfterLogin";

import PresentBar from "./components/PresentBar.vue";
import TitleBar from "./components/TitleBar.vue";
Expand Down
Loading

0 comments on commit 80e1d32

Please sign in to comment.