navbar新增消息通知

This commit is contained in:
不做码农 2022-04-25 18:35:28 +08:00
parent bf625f2ca6
commit 4ad53af42d
6 changed files with 154 additions and 21 deletions

View File

@ -12,4 +12,4 @@ VITE_APP_ROUTER_PREFIX = '/'
VITE_APP_UPLOAD_URL = '/Common/UploadFile' VITE_APP_UPLOAD_URL = '/Common/UploadFile'
#socket API #socket API
VITE_APP_SOCKET_API = 'http://localhost:8888/msghub' VITE_APP_SOCKET_API = '/msghub'

View File

@ -0,0 +1,107 @@
<template>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">通知</div>
<div class="head-box-btn" v-if="noticeList.length > 0" @click="onAllReadClick">全部已读</div>
</div>
<div class="content-box">
<template v-if="noticeList.length > 0">
<div class="content-box-item" v-for="(v, k) in noticeList" :key="k">
<div>{{ v.noticeTitle }}</div>
<div class="content-box-msg" v-html="v.noticeContent"></div>
<div class="content-box-time">{{ v.updateTime }}</div>
</div>
</template>
<div class="content-box-empty" v-else>
<div class="content-box-empty-margin">
<i class="el-icon-s-promotion"></i>
<div class="mt15">全部已读</div>
</div>
</div>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="noticeList.length > 0">前往通知中心</div>
</div>
</template>
<script setup name="noticeIndex">
const { proxy } = getCurrentInstance()
const noticeList = computed(() => {
return proxy.$store.getters.noticeList
})
//
function onAllReadClick() {
proxy.$modal.msg('敬请期待!!!')
}
//
function onGoToGiteeClick() {
window.open('https://gitee.com/izory/ZrAdminNetCore')
}
</script>
<style lang="scss">
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
color: #333333;
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: #1890ff;
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
font-size: 13px;
.content-box-item {
padding-top: 12px;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: #999999;
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: #999999;
}
}
.content-box-empty {
height: 260px;
display: flex;
.content-box-empty-margin {
margin: auto;
text-align: center;
i {
font-size: 60px;
}
}
}
}
.foot-box {
height: 35px;
color: #1890ff;
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid #ebeef5;
&:hover {
opacity: 1;
}
}
:deep(.el-empty__description p) {
font-size: 13px;
}
}
</style>

View File

@ -22,6 +22,17 @@
<size-select id="size-select" class="right-menu-item hover-effect" /> <size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
</template> </template>
<!-- 通知 -->
<div class="right-menu-item">
<el-popover placement="bottom" trigger="click" v-model:visible="isShowUserNewsPopover" width="300" popper-class="el-popover-pupop-user-news">
<template #reference>
<el-badge @click.stop="isShowUserNewsPopover = !isShowUserNewsPopover" :is-dot="true" slot="reference" style="line-height: 32px">
<el-icon><bell /></el-icon>
</el-badge>
</template>
<Notice v-show="isShowUserNewsPopover" />
</el-popover>
</div>
<div class="avatar-container"> <div class="avatar-container">
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click"> <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
@ -59,9 +70,11 @@ import SizeSelect from '@/components/SizeSelect'
import HeaderSearch from '@/components/HeaderSearch' import HeaderSearch from '@/components/HeaderSearch'
import ZrGit from '@/components/Zr/Git' import ZrGit from '@/components/Zr/Git'
import ZrDoc from '@/components/Zr/Doc' import ZrDoc from '@/components/Zr/Doc'
import Notice from '@/components/Notice/Index'
const store = useStore() const store = useStore()
const getters = computed(() => store.getters) const getters = computed(() => store.getters)
const isShowUserNewsPopover = ref(false)
function toggleSideBar() { function toggleSideBar() {
store.dispatch('app/toggleSideBar') store.dispatch('app/toggleSideBar')
@ -100,7 +113,7 @@ function setLayout() {
} }
</script> </script>
<style lang='scss' scoped> <style lang="scss" scoped>
.el-menu { .el-menu {
// display: inline-table; // display: inline-table;
line-height: 46px !important; line-height: 46px !important;

View File

@ -10,26 +10,27 @@ export default {
// 失败连接重试次数 // 失败连接重试次数
failNum: 4, failNum: 4,
baseUrl: '', baseUrl: '',
init(url) { init(url) {
console.log(url); var socketUrl = window.location.origin + url
//console.log(socketUrl)
const connection = new signalR.HubConnectionBuilder() const connection = new signalR.HubConnectionBuilder()
.withUrl(url, { accessTokenFactory: () => getToken() }) .withUrl(socketUrl, { accessTokenFactory: () => getToken() })
.withAutomaticReconnect()//自动重新连接 .withAutomaticReconnect() //自动重新连接
.configureLogging(signalR.LogLevel.Information) .configureLogging(signalR.LogLevel.Information)
.build(); .build();
this.SR = connection; this.SR = connection
// 断线重连 // 断线重连
connection.onclose(async () => { connection.onclose(async () => {
console.log('断开连接了') console.log('断开连接了')
console.assert(connection.state === signalR.HubConnectionState.Disconnected); console.assert(connection.state === signalR.HubConnectionState.Disconnected);
// 建议用户重新刷新浏览器 // 建议用户重新刷新浏览器
await this.start(); await this.start()
}) })
connection.onreconnected(() => { connection.onreconnected(() => {
console.log('断线重新连接成功') console.log('断线重新连接成功')
}) })
this.receiveMsg(connection); this.receiveMsg(connection)
// 启动 // 启动
// this.start(); // this.start();
}, },
@ -38,26 +39,26 @@ export default {
* @returns * @returns
*/ */
async start() { async start() {
var that = this; var that = this
try { try {
//使用async和await 或 promise的then 和catch 处理来自服务端的异常 //使用async和await 或 promise的then 和catch 处理来自服务端的异常
await this.SR.start(); await this.SR.start()
//console.assert(this.SR.state === signalR.HubConnectionState.Connected); //console.assert(this.SR.state === signalR.HubConnectionState.Connected);
console.log('signalR 连接成功了', this.SR.state); console.log('signalR 连接成功了', this.SR.state);
return true; return true
} catch (error) { } catch (error) {
that.failNum--; that.failNum--;
console.log(`失败重试剩余次数${that.failNum}`, error) console.log(`失败重试剩余次数${that.failNum}`, error)
if (that.failNum > 0) { if (that.failNum > 0) {
setTimeout(async () => { setTimeout(async () => {
await this.SR.start() await this.SR.start()
}, 5000); }, 5000)
} }
return false; return false
} }
}, },
// 接收消息处理 // 接收消息处理
receiveMsg(connection) { receiveMsg(connection) {
connection.on("onlineNum", (data) => { connection.on("onlineNum", (data) => {
store.dispatch("socket/changeOnlineNum", data); store.dispatch("socket/changeOnlineNum", data);

View File

@ -54,6 +54,7 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-button type="text" icon="bell" @click="handleNotice(scope.row)" v-hasPermi="['system:notice:edit']">通知</el-button>
<el-button type="text" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:notice:edit']">修改</el-button> <el-button type="text" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:notice:edit']">修改</el-button>
<el-button type="text" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:notice:remove']">删除</el-button> <el-button type="text" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:notice:remove']">删除</el-button>
</template> </template>
@ -105,8 +106,8 @@
<script setup name="notice"> <script setup name="notice">
// //
import Editor from '@/components/Editor' import Editor from '@/components/Editor'
import { listNotice, getNotice, delNotice, addNotice, updateNotice } from '@/api/system/notice' import { listNotice, getNotice, delNotice, addNotice, updateNotice, sendNotice } from '@/api/system/notice'
import { getCurrentInstance } from 'vue'; import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const noticeList = ref([]) const noticeList = ref([])
@ -236,6 +237,12 @@ function handleDelete(row) {
}) })
.catch(() => {}) .catch(() => {})
} }
//
function handleNotice(row) {
const noticeId = row.noticeId || ids.value
sendNotice(noticeId).then((res) => {
proxy.$modal.msgSuccess('发送通知成功')
})
}
getList() getList()
</script> </script>

View File

@ -39,7 +39,12 @@ export default defineConfig(({ mode, command }) => {
target: 'http://localhost:8888', target: 'http://localhost:8888',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/dev-api/, '') rewrite: (path) => path.replace(/^\/dev-api/, '')
} },
'/msghub': {
target: 'http://localhost:8888',
ws: true,
rewrite: (path) => path.replace(/^\/msgHub/, '')
}
}, },
}, },
} }