navbar新增消息通知
This commit is contained in:
parent
bf625f2ca6
commit
4ad53af42d
@ -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'
|
||||||
107
src/components/Notice/Index.vue
Normal file
107
src/components/Notice/Index.vue
Normal 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>
|
||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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/, '')
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user