赞
踩
更多ruoyi-nbcio功能请看演示系统
gitee源代码地址
前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio
演示地址:RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/
更多nbcio-boot功能请看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://122.227.135.243:9888
1、在navbar.vue里增加消息组件
- <!-- 消息 -->
- <el-tooltip :content="$t('navbar.message')" effect="dark" placement="bottom">
- <header-notice id="message" class="right-menu-item hover-effect" />
- </el-tooltip>
就是在右上角显示消息图标bell
2、HeadNotice.vue文件vue3版本修改如下:
- <template>
- <div>
- <a-popover trigger="click" placement="bottomRight" :autoAdjustOverflow="true" :arrowPointAtCenter="true"
- overlayClassName="header-notice-wrapper" @visibleChange="handleHoverChange"
- :overlayStyle="{ width: '400px', top: '50px' }">
- <template #content>
- <a-spin :spinning="loadding">
- <a-tabs>
- <a-tab-pane :tab="msg1Title" key="1">
- <a-list>
- <a-list-item :key="index" v-for="(record, index) in notice1">
- <div style="margin-left: 5%;width: 50%">
- <p><a @click="showNoticeList(record)">{{ record.titile }}</a></p>
- <p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
- </div>
- <div style="text-align: right">
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'L'" color="blue">一般消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'M'" color="orange">重要消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'H'" color="red">紧急消息</a-tag>
- </div>
- </a-list-item>
- <div style="margin-top: 5px;text-align: center">
- <a-button @click="toMyNotice()" type="dashed" block>查看更多</a-button>
- </div>
- </a-list>
- </a-tab-pane>
- <a-tab-pane :tab="msg2Title" key="2">
- <a-list>
- <a-list-item :key="index" v-for="(record, index) in notice2">
- <div style="margin-left: 5%;width: 50%">
- <p><a @click="showNoticeList(record)">{{ record.titile }}</a></p>
- <p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
- </div>
- <div style="text-align: right">
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'L'" color="blue">一般消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'M'" color="orange">重要消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'H'" color="red">紧急消息</a-tag>
- </div>
- </a-list-item>
- <div style="margin-top: 5px;text-align: center">
- <a-button @click="toMyNotice()" type="dashed" block>查看更多</a-button>
- </div>
- </a-list>
- </a-tab-pane>
- <a-tab-pane :tab="msg3Title" key="3">
- <a-list>
- <a-list-item :key="index" v-for="(record, index) in notice3">
- <div style="margin-left: 5%;width: 50%">
- <p><a @click="showNoticeList(record)">{{ record.titile }}</a></p>
- <p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
- </div>
- <div style="text-align: right">
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'L'" color="blue">一般消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'M'" color="orange">重要消息</a-tag>
- <a-tag @click="showNoticeList(record)" v-if="record.priority === 'H'" color="red">紧急消息</a-tag>
- </div>
- </a-list-item>
- <div style="margin-top: 5px;text-align: center">
- <a-button @click="toMyNotice()" type="dashed" block>查看更多</a-button>
- </div>
- </a-list>
- </a-tab-pane>
- </a-tabs>
- </a-spin>
- </template>
- <span @click="fetchNotice" class="header-notice">
- <a-badge :count="msgTotal">
- <svg-icon icon-class="bell" style="width: 18px;height:18px;" />
- </a-badge>
- </span>
- <show-notice ref="showNoticeRef" @ok="modalFormOk"></show-notice>
- <dynamic-notice ref="showDynamNoticeRef" :path="openPath" :formData="formData" />
- </a-popover>
- </div>
- </template>
-
- <script setup lang="ts">
- import ShowNotice from './ShowNotice.vue'
- import useUserStore from '@/store/modules/user';
- import DynamicNotice from './DynamicNotice'
- import { ElNotification } from "element-plus";
- import { listByUser, updateUserIdAndNotice } from "@/api/system/notice";
-
- const router = useRouter();
- const userStore = useUserStore();
-
- const loadding = ref(false)
- const hovered = ref(false)
- const notice1 = ref<any>([])
- const notice2 = ref<any>([])
- const notice3 = ref<any>([])
- const msg1Count = ref("0")
- const msg2Count = ref("0")
- const msg3Count = ref("0")
- const msg1Title = ref("通知(0)")
- const msg2Title = ref("")
- const msg3Title = ref("")
- const stopTimer = ref(false)
- let websock : any = null; // websocket 实例
- const lockReconnect = ref(false)
- const formData = ref<any>({})
- const openPath = ref('')
- const showDynamNoticeRef = ref(DynamicNotice)
- const showNoticeRef = ref(ShowNotice)
-
- const loadData = () => {
- try {
- // 获取系统消息
- listByUser().then((res) => {
- console.log("listByUser res",res);
- if (res.code == 200) {
- notice1.value = res.data.anntMsgList;
- msg1Count.value = res.data.anntMsgTotal;
- msg1Title.value = "通知(" + res.data.anntMsgTotal + ")";
- notice2.value = res.data.sysMsgList;
- msg2Count.value = res.data.sysMsgTotal;
- msg2Title.value = "系统消息(" + res.data.sysMsgTotal + ")";
- notice3.value = res.data.todealMsgList;
- msg3Count.value = res.data.todealMsgTotal;
- msg3Title.value = "待办消息(" + res.data.todealMsgTotal + ")";
- }
- }).catch(error => {
- console.log("系统消息通知异常", error); //这行打印permissionName is undefined
- stopTimer.value = true;
- console.log("清理timer");
- });
- } catch (err) {
- stopTimer.value = true;
- console.log("通知异常", err);
- }
- }
- const fetchNotice = () => {
- if (loadding.value) {
- loadding.value = false
- return
- }
- loadding.value = true
- setTimeout(() => {
- loadding.value = false
- }, 200)
- }
- const showNoticeList = (record: any) => {
- updateUserIdAndNotice({
- noticeId: record.noticeId
- }).then((res) => {
- if (res.code == 200) {
- loadData();
- }
- });
- hovered.value = false;
- if (record.openType === 'component') {
- openPath.value = record.openPage;
- formData.value = {
- id: record.busId
- };
- showDynamNoticeRef.value.detail(record.openPage);
- } else {
- console.log("showNoticeList showNoticeRef",showNoticeRef.value)
- showNoticeRef.value.detail(record);
- }
- }
- const toMyNotice = () => {
- router.push({
- path: '/personal/mynotice'
- });
- }
- const modalFormOk = () =>{
-
- }
- const handleHoverChange = (visible: any) => {
- hovered.value = visible;
- }
-
- const initWebSocket = () => {
- // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
- var userName = userStore.name;
- //var url = import.meta.env.VITE_APP_WS_API + "/websocket/" + userName + "?Authorization=Bearer " + getToken() + "&clientid=" + import.meta.env.VITE_APP_CLIENT_ID;
- var url = import.meta.env.VITE_APP_WS_API + "/websocket/" + userName;
- console.log("initWebSocket url=",url);
- websock = new WebSocket(url);
- websock.onopen = websocketOnopen;
- websock.onerror = websocketOnerror;
- websock.onmessage = websocketOnmessage;
- websock.onclose = websocketOnclose;
- }
- const websocketOnopen = () => {
- console.log("WebSocket连接成功");
- }
- const websocketOnerror = (e) => {
- console.log("WebSocket连接发生错误");
- reconnect();
- }
- const websocketOnmessage = (e) => {
- console.log("-----接收消息-------", e);
- console.log("-----接收消息-------", e.data);
- var data = eval("(" + e.data + ")"); //解析对象
- if (data.cmd == "topic") {
- //系统通知
- loadData();
- ElNotification({ //websocket消息通知弹出
- title: 'websocket消息通知',
- message: data.msgTxt,
- type: 'success',
- duration: 1000
- })
- } else if (data.cmd == "user") {
- //用户消息
- loadData();
- ElNotification({
- title: 'websocket消息通知',
- message: data.msgTxt,
- type: 'success',
- duration: 1000
- })
- }
- }
- const websocketOnclose = (e) => {
- console.log("connection closed (" + e + ")");
- if (e) {
- console.log("connection closed (" + e.code + ")");
- }
- reconnect();
- }
- const websocketSend = (text) => { // 数据发送
- try {
- websock.send(text);
- } catch (err) {
- console.log("send failed (" + err.code + ")");
- }
- }
-
- const openNotification = (data) =>{
- var text = data.msgTxt;
- const key = `open${Date.now()}`;
- ElNotification({
- title: '消息提醒',
- message: text,
- type: 'success',
- duration: 1000
- })
- }
-
- const reconnect = () => {
- if (lockReconnect.value) return;
- lockReconnect.value = true;
- //没连接上会一直重连,设置延迟避免请求过多
- setTimeout(function() {
- console.info("尝试重连...");
- initWebSocket();
- lockReconnect.value = false;
- }, 5000);
- }
-
- const showDetail = (key, data) => {
- ElNotification[key].close();
- var id = data.msgId;
- getAction(url.queryById, {
- id: id
- }).then((res) => {
- if (res.success) {
- var record = res.result;
- showNotice(record);
- }
- })
-
- }
- const msgTotal = computed(() => {
- return parseInt(msg1Count.value) + parseInt(msg2Count.value) + parseInt(msg3Count.value);
- })
-
- onMounted(() => {
- loadData();
- initWebSocket();
- })
-
- onUnmounted(() => {
- websocketOnclose('');
- })
- </script>
-
- <style lang="css">
- .header-notice-wrapper {
- top: 50px !important;
- }
- </style>
- <style lang="less" scoped>
- .header-notice {
- display: inline-block;
- transition: all 0.3s;
-
- span {
- vertical-align: initial;
- }
- }
- </style>
3、ShowNotice.vue文件vue3版本修改如下:
- <template>
- <n-modal
- :title="title"
- :width="modelStyle.width"
- :visible="visible"
- :bodyStyle ="bodyStyle"
- @cancel="handleCancel"
- >
- <template #footer>
- <a-button key="back" @click="handleCancel">关闭</a-button>
- <a-button v-if="recordDetail.openType==='url'" type="primary" @click="toHandle">去处理</a-button>
- </template>
- <a-card class="daily-article" :loading="loading">
- <a-card-meta
- :title="recordDetail.noticeTitle"
- :description="'发布人:'+recordDetail.sender + ' 发布时间: ' + recordDetail.sendTime">
- </a-card-meta>
- <a-divider />
- <span v-html="recordDetail.noticeContent" class="article-content"></span>
- </a-card>
- </n-modal>
- </template>
-
- <script setup lang="ts" name="ShowNotice">
-
- import NModal from './NModal'
-
- const router = useRouter();
- const title = ref("通知消息")
- const recordDetail = ref<any>({})
-
- const visible = ref(false)
- const loading = ref(false)
- const bodyStyle = ref({
- padding: "0",
- height:(window.innerHeight*0.8)+"px",
- "overflow-y":"auto",
- })
- const modelStyle = ref({
- width: '60%',
- style: { top: '20px' },
- fullScreen: false
- })
-
- const detail = (record: any) => {
- visible.value = true;
- recordDetail.value = toRaw(record);
- }
-
- const handleCancel = () => {
- visible.value = false;
- }
-
- const toHandle = () => {
- if(recordDetail.value.openType==='url'){
- visible.value = false;
- //链接跳转
- router.push({path: recordDetail.value.openPage})
- }
- }
-
- //暴露detail方法
- defineExpose({
- detail
- });
-
- onMounted(() => {
- console.log("ShowNotice visible",visible)
- })
-
- </script>
-
- <style lang="less" scoped>
- .announcementCustomModal{
- .ant-modal-header {
- border: none;
- display: inline-block;
- position: absolute;
- z-index: 1;
- right: 56px;
- padding: 0;
- .ant-modal-title{
- .custom-btn{
- width: 56px;
- height: 56px;
- border: none;
- box-shadow: none;
- }
- }
- }
- .daily-article{
- border-bottom: 0;
- }
- }
- .daily-article {
- .article-button {
- font-size: 1.2rem !important;
- }
- .ant-card-body {
- padding: 18px !important;
- }
- .ant-card-head {
- padding: 0 1rem;
- }
- .ant-card-meta {
- margin-bottom: 1rem;
- }
- .article-content {
- p {
- word-wrap: break-word;
- word-break: break-all;
- text-overflow: initial;
- white-space: normal;
- font-size: .9rem !important;
- margin-bottom: .8rem;
- }
- :deep(a) {
- color: #1890ff;
- }
- }
- }
- </style>
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。