'123'
This commit is contained in:
parent
e4bdf650bb
commit
9681fd1a48
|
@ -1,6 +1,14 @@
|
||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.ruoyi.common.constant.WebsocketConst;
|
||||||
|
import com.ruoyi.framework.websocket.WebSocketServer;
|
||||||
|
import com.ruoyi.framework.websocket.WebSocketUsers;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
@ -32,6 +40,9 @@ public class SysNoticeController extends BaseController
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISysNoticeService noticeService;
|
private ISysNoticeService noticeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebSocketServer webSocketServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取通知公告列表
|
* 获取通知公告列表
|
||||||
*/
|
*/
|
||||||
|
@ -63,6 +74,13 @@ public class SysNoticeController extends BaseController
|
||||||
public AjaxResult add(@Validated @RequestBody SysNotice notice)
|
public AjaxResult add(@Validated @RequestBody SysNotice notice)
|
||||||
{
|
{
|
||||||
notice.setCreateBy(getUsername());
|
notice.setCreateBy(getUsername());
|
||||||
|
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put(WebsocketConst.MSG_ID, notice.getNoticeId());
|
||||||
|
obj.put(WebsocketConst.MSG_TITLE, notice.getNoticeTitle());
|
||||||
|
obj.put(WebsocketConst.MSG_CONTENT, notice.getNoticeContent());
|
||||||
|
WebSocketUsers.sendMessageToUsersByText(obj.toString());
|
||||||
|
|
||||||
return toAjax(noticeService.insertNotice(notice));
|
return toAjax(noticeService.insertNotice(notice));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,4 +106,21 @@ public class SysNoticeController extends BaseController
|
||||||
{
|
{
|
||||||
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航面板 消息通知
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@GetMapping("/navbarNoticelist")
|
||||||
|
public Map<String, List<SysNotice>> navbarNoticelist()
|
||||||
|
{
|
||||||
|
List<SysNotice> list = noticeService.navbarNoticelist();
|
||||||
|
Map<String, List<SysNotice>> groupedByNoticeType = list.stream()
|
||||||
|
.collect(Collectors.groupingBy(SysNotice::getNoticeType));
|
||||||
|
for(String key:groupedByNoticeType.keySet()){
|
||||||
|
List<SysNotice> lt = groupedByNoticeType.get(key);
|
||||||
|
lt.sort((t1, t2) -> t2.getCreateTime().compareTo(t1.getCreateTime()));
|
||||||
|
}
|
||||||
|
return groupedByNoticeType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.ruoyi.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送通用常量
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
*/
|
||||||
|
public class WebsocketConst {
|
||||||
|
/** 消息ID */
|
||||||
|
public static final String MSG_ID = "noticeId";
|
||||||
|
|
||||||
|
/** 消息TITLE */
|
||||||
|
public static final String MSG_TITLE = "noticeTitle";
|
||||||
|
|
||||||
|
/** 消息CONTENT */
|
||||||
|
public static final String MSG_CONTENT = "noticeContent";
|
||||||
|
}
|
|
@ -57,4 +57,10 @@ public interface SysNoticeMapper
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteNoticeByIds(Long[] noticeIds);
|
public int deleteNoticeByIds(Long[] noticeIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息推送信息获取
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<SysNotice> navbarNoticelist();
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,4 +57,10 @@ public interface ISysNoticeService
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteNoticeByIds(Long[] noticeIds);
|
public int deleteNoticeByIds(Long[] noticeIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航面板 消息通知
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<SysNotice> navbarNoticelist();
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,4 +112,13 @@ public class SysNoticeServiceImpl implements ISysNoticeService
|
||||||
{
|
{
|
||||||
return noticeMapper.deleteNoticeByIds(noticeIds);
|
return noticeMapper.deleteNoticeByIds(noticeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导航面板 消息通知
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<SysNotice> navbarNoticelist() {
|
||||||
|
return noticeMapper.navbarNoticelist();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,4 +86,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</foreach>
|
</foreach>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
<select id="navbarNoticelist" resultMap="SysNoticeResult">
|
||||||
|
<include refid="selectNoticeVo"/>
|
||||||
|
<where>
|
||||||
|
CONVERT(date, create_time) = CONVERT(date, GETDATE())
|
||||||
|
</where>
|
||||||
|
order by create_time desc
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询业务消息
|
|
||||||
export function getNoticeListTop3(query) {
|
|
||||||
return request({
|
|
||||||
url: '/system/notice/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -42,3 +42,12 @@ export function delNotice(noticeId) {
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 导航面板 消息通知
|
||||||
|
export function navbarNoticelist(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/notice/navbarNoticelist',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||||
</el-tooltip>-->
|
</el-tooltip>-->
|
||||||
|
|
||||||
|
<!--消息组件-->
|
||||||
|
<NavbarNotice class="right-menu-item hover-effect"></NavbarNotice>
|
||||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||||
|
|
||||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||||
|
@ -57,18 +59,9 @@ import Search from '@/components/HeaderSearch'
|
||||||
import RuoYiGit from '@/components/RuoYi/Git'
|
import RuoYiGit from '@/components/RuoYi/Git'
|
||||||
import RuoYiDoc from '@/components/RuoYi/Doc'
|
import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||||
import settings from '@/settings'
|
import settings from '@/settings'
|
||||||
|
import NavbarNotice from "@/layout/components/NavbarNotice.vue";
|
||||||
import { getNoticeListTop3 } from "@/api/system/businessNotice";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
url: "ws://localhost:3334/websocket/message",
|
|
||||||
message: "",
|
|
||||||
text_content: "",
|
|
||||||
ws: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
components: {
|
components: {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
TopNav,
|
TopNav,
|
||||||
|
@ -77,7 +70,8 @@ export default {
|
||||||
SizeSelect,
|
SizeSelect,
|
||||||
Search,
|
Search,
|
||||||
RuoYiGit,
|
RuoYiGit,
|
||||||
RuoYiDoc
|
RuoYiDoc,
|
||||||
|
NavbarNotice
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
|
@ -102,87 +96,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
/** 消息推送 */
|
|
||||||
this.notice();
|
|
||||||
const wsuri = this.url;
|
|
||||||
this.ws = new WebSocket(wsuri);
|
|
||||||
const self = this;
|
|
||||||
this.ws.onopen = function (event) {
|
|
||||||
//self.text_content = self.text_content + "已经打开连接!" + "\n";
|
|
||||||
};
|
|
||||||
this.ws.onmessage = function (event) {
|
|
||||||
//self.text_content = event.data + "\n";
|
|
||||||
var messageBody = JSON.parse(event.data);
|
|
||||||
Notification.info({
|
|
||||||
title: "通知",
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
message: messageBody.noticeContent,
|
|
||||||
duration: 0,
|
|
||||||
offset: 40,
|
|
||||||
onClick: function () {
|
|
||||||
//self.warnDetailByWarnid(messageBody.warnId); //自定义回调,message为传的参数
|
|
||||||
// 点击跳转的页面
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
this.ws.onclose = function (event) {
|
|
||||||
//self.text_content = self.text_content + "已经关闭连接!" + "\n";
|
|
||||||
};
|
|
||||||
/** 消息推送 */
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
/** 消息推送 */
|
|
||||||
notice() {
|
|
||||||
getNoticeListTop3().then(response => {
|
|
||||||
for (let i = 0; i < response.length; i++) {
|
|
||||||
let messageBody = response[i];
|
|
||||||
setTimeout(() => {
|
|
||||||
this.notificationInfo(messageBody);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
notificationInfo(messageBody) {
|
|
||||||
Notification.info({
|
|
||||||
title: "通知",
|
|
||||||
dangerouslyUseHTMLString: true,
|
|
||||||
message: messageBody.noticeContent,
|
|
||||||
duration: 0,
|
|
||||||
offset: 40,
|
|
||||||
onClick: function () {
|
|
||||||
//self.warnDetailByWarnid(messageBody.warnId); //自定义回调,message为传的参数
|
|
||||||
// 点击跳转的页面
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// join() {
|
|
||||||
//
|
|
||||||
// },
|
|
||||||
exit() {
|
|
||||||
if (this.ws) {
|
|
||||||
this.ws.close();
|
|
||||||
this.ws = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
send() {
|
|
||||||
if (this.ws) {
|
|
||||||
this.ws.send(this.message);
|
|
||||||
} else {
|
|
||||||
alert("未连接到服务器");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
warnDetailByWarnid(warnid) {
|
|
||||||
// 跳转预警详情页面
|
|
||||||
this.$router.push({
|
|
||||||
path: "/XXX/XXX",
|
|
||||||
query: {
|
|
||||||
warnid: warnid,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
/** 消息推送 */
|
|
||||||
|
|
||||||
toggleSideBar() {
|
toggleSideBar() {
|
||||||
this.$store.dispatch('app/toggleSideBar')
|
this.$store.dispatch('app/toggleSideBar')
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
<template>
|
||||||
|
<!--(1通知 2公告)-->
|
||||||
|
<el-dropdown>
|
||||||
|
<span class="el-dropdown-link">
|
||||||
|
<svg-icon icon-class="message" slot="reference" />
|
||||||
|
<el-badge :value="noteTotal"></el-badge>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-tabs v-model="activeName" @tab-click="handleClick" style="width:100%">
|
||||||
|
<el-tab-pane label="系统通知" name="first">
|
||||||
|
<el-dropdown-item v-for="(item,index) in noticeData" :key="index" >
|
||||||
|
<el-link :underline="false" @click="clickNote(item)" :style="index==0?'': 'margin-top :15px'">{{item.noticeTitle}}</el-link>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-link :underline="false" style="margin-top :15px" v-if="noticeData.length>5" type="primary">更多消息</el-link>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="系统公告" name="second">
|
||||||
|
<el-dropdown-item v-for="(item,index) in sysLog" :key="index">
|
||||||
|
<el-link :underline="false" @click="clickNote(item)" :style="index==0?'': 'margin-top :15px'">{{item.noticeTitle}}</el-link>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-link v-if="sysLog.length>5" type="primary">更多消息</el-link>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
<!--<mode-dialog :visible="noteVisible" :noteType="noteType" :noticeId="noticeId" @close="closeMode"></mode-dialog>-->
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { navbarNoticelist } from '@/api/system/notice'
|
||||||
|
/*
|
||||||
|
import ModeDialog from '@/components/ModeDialog'
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'NavbarNotice',
|
||||||
|
/*
|
||||||
|
components: { ModeDialog },
|
||||||
|
*/
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: 'first',
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
readFlag: '0'
|
||||||
|
},
|
||||||
|
noteTotal: '',
|
||||||
|
// 公告
|
||||||
|
sysLog: [],
|
||||||
|
// 通知
|
||||||
|
noticeData: [],
|
||||||
|
websock: null,
|
||||||
|
lockReconnect: false,
|
||||||
|
heartCheck: null,
|
||||||
|
noteVisible: false,
|
||||||
|
noteType: 0,
|
||||||
|
noticeId: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 初始化WebSocket
|
||||||
|
this.initWebSocket()
|
||||||
|
},
|
||||||
|
destroyed: function() { // 离开页面生命周期函数
|
||||||
|
this.websocketOnclose()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getList() {
|
||||||
|
this.noticeData = []
|
||||||
|
this.sysLog = []
|
||||||
|
navbarNoticelist(this.queryParams).then(res => {
|
||||||
|
console.log(res[1])
|
||||||
|
this.noticeData = res[1]?res[1]:[];
|
||||||
|
this.sysLog = res[2]?res[2]:[];
|
||||||
|
|
||||||
|
this.noteTotal = this.noticeData.length+this.sysLog.length;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleClick(tab, event) {
|
||||||
|
},
|
||||||
|
clickNote(data) {
|
||||||
|
this.noteVisible = true
|
||||||
|
this.noticeId = data.noticeId
|
||||||
|
this.noteType = data.noticeType == '1' ? 0 : 1
|
||||||
|
},
|
||||||
|
closeMode() {
|
||||||
|
this.getList()
|
||||||
|
this.noteVisible = false
|
||||||
|
},
|
||||||
|
initWebSocket() {
|
||||||
|
var userId = this.$store.getters.userId
|
||||||
|
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
|
||||||
|
// VUE_APP_BASE_API_WS = 'ws://localhost:9696' 地址
|
||||||
|
var url = 'ws://localhost:3334/websocket/message';
|
||||||
|
this.websock = new WebSocket(url)
|
||||||
|
this.websock.onopen = this.websocketOnopen
|
||||||
|
this.websock.onerror = this.websocketOnerror
|
||||||
|
this.websock.onmessage = this.websocketOnmessage
|
||||||
|
this.websock.onclose = this.websocketOnclose
|
||||||
|
},
|
||||||
|
websocketOnopen: function() {
|
||||||
|
console.log('WebSocket连接成功')
|
||||||
|
},
|
||||||
|
websocketOnerror: function(e) {
|
||||||
|
console.log('WebSocket连接发生错误,第%s次', this.wsConnectErrorTime)
|
||||||
|
this.wsConnectErrorTime = this.wsConnectErrorTime + 1
|
||||||
|
if (this.wsConnectErrorTime > 5) {
|
||||||
|
console.log('WebSocket连接错误超过5次,就不再重新连了!')
|
||||||
|
this.lockReconnect = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.reconnect()
|
||||||
|
},
|
||||||
|
websocketOnmessage: function(e) {
|
||||||
|
console.log('-----接收消息-------', e.data)
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
websocketOnclose: function(e) {
|
||||||
|
console.log('connection closed (' + e + ')')
|
||||||
|
if (e) {
|
||||||
|
console.log('connection closed (' + e.code + ')')
|
||||||
|
}
|
||||||
|
this.reconnect()
|
||||||
|
},
|
||||||
|
reconnect() {
|
||||||
|
var that = this
|
||||||
|
if (that.lockReconnect) return
|
||||||
|
that.lockReconnect = true
|
||||||
|
//没连接上会一直重连,设置延迟避免请求过多
|
||||||
|
setTimeout(function() {
|
||||||
|
console.info('尝试重连...')
|
||||||
|
that.initWebSocket()
|
||||||
|
that.lockReconnect = false
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.text-overflow {
|
||||||
|
width: 160px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-badge {
|
||||||
|
top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-badge__content.is-dot {
|
||||||
|
position: relative;
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tab-pane{
|
||||||
|
width:300px
|
||||||
|
}
|
||||||
|
.el-dropdown-menu{
|
||||||
|
width:250px
|
||||||
|
}
|
||||||
|
::v-deep .el-dropdown-menu {
|
||||||
|
top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-tabs {
|
||||||
|
padding: 12px;
|
||||||
|
width: 188px;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue