This commit is contained in:
xd 2024-04-25 13:24:18 +08:00
parent b3a429204f
commit 00cd608378
9 changed files with 201 additions and 57 deletions

View File

@ -9,6 +9,7 @@ import com.ruoyi.framework.websocket.OneToManyWebSocket;
import com.ruoyi.framework.websocket.WebSocketServer;
import com.ruoyi.framework.websocket.WebSocketUsers;
import com.ruoyi.system.domain.SysNoticeUser;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
@ -77,26 +78,9 @@ public class SysNoticeController extends BaseController
{
notice.setCreateBy(getUsername());
noticeService.insertNotice(notice);
List<SysNoticeUser> sysNoticeUsers = new ArrayList<SysNoticeUser>();
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());
if(!"3".equals(notice.getNoticeType())){//系统通知 通知公告
oneToManyWebSocket.sendMessage(obj.toString());
SysNoticeUser sysNoticeUser = null;
Map<String, Session> users = oneToManyWebSocket.getUsers();
for(String userId:users.keySet()){
sysNoticeUser = new SysNoticeUser();
sysNoticeUser.setNoticeId(notice.getNoticeId());
sysNoticeUser.setUserId(Long.valueOf(userId));
sysNoticeUsers.add(sysNoticeUser);
}
noticeService.insertNoticeUserBatch(sysNoticeUsers);
}
//推送消息插入中间表
Long userId = getLoginUser().getUserId();//当前登陆者
insertNoticeUser(userId,notice,noticeService,oneToManyWebSocket,null);
return success();
}
@ -140,4 +124,65 @@ public class SysNoticeController extends BaseController
}
return groupedByNoticeType;
}
/**
* 导航面板 消息通知 获取详细信息
*/
@GetMapping(value = "navbarNotice/{noticeId}")
public AjaxResult getNavbarNoticeInfo(@PathVariable Long noticeId)
{
return success(noticeService.selectNoticeById(noticeId));
}
/**
* 推送消息插入中间表
* @param userId 发送对象排除自身
* @param notice 发送信息对象
* @param noticeService 接口
* @param oneToManyWebSocket WebSocket服务
*/
public static void insertNoticeUser(Long userId,SysNotice notice,ISysNoticeService noticeService,OneToManyWebSocket oneToManyWebSocket,List<String> userIds){
List<SysNoticeUser> sysNoticeUsers = new ArrayList<SysNoticeUser>();
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());
if(!"3".equals(notice.getNoticeType())){//系统通知 通知公告
oneToManyWebSocket.sendMessage(obj.toString(),String.valueOf(userId));
SysNoticeUser sysNoticeUser = null;
Map<String, Session> users = oneToManyWebSocket.getUsers();//获取在线用户
for(String userid:users.keySet()){
if(!userid.equals(String.valueOf(userId))){
sysNoticeUser = new SysNoticeUser();
sysNoticeUser.setNoticeId(notice.getNoticeId());
sysNoticeUser.setUserId(Long.valueOf(userid));
sysNoticeUsers.add(sysNoticeUser);
}
}
if(!sysNoticeUsers.isEmpty()){
noticeService.insertNoticeUserBatch(sysNoticeUsers);
}
}else{
if(userIds!=null&&userIds.size()>0){
oneToManyWebSocket.sendMessageByUserIds(obj.toString(),userIds);
SysNoticeUser sysNoticeUser = null;
Map<String, Session> users = oneToManyWebSocket.getUsers();//获取在线用户
for(String userid:users.keySet()){
if(userIds.contains(userid)){
sysNoticeUser = new SysNoticeUser();
sysNoticeUser.setNoticeId(notice.getNoticeId());
sysNoticeUser.setUserId(Long.valueOf(userid));
sysNoticeUsers.add(sysNoticeUser);
}
}
if(!sysNoticeUsers.isEmpty()){
noticeService.insertNoticeUserBatch(sysNoticeUsers);
}
}
}
}
}

View File

@ -90,29 +90,30 @@ public class OneToManyWebSocket {
/**
* 群发消息
*
* @param message
* @param userId
*/
public static void sendMessage(String message) {
public static void sendMessage(String message,String userId) {
for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
Session toSession = sessionEntry.getValue();
String suid = sessionEntry.getKey();
// 排除掉自己
//if (!fromSession.getId().equals(toSession.getId())) {
if (!suid.equals(userId)) {
LOGGER.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
toSession.getAsyncRemote().sendText(message);
//}
}
}
}
/**
* 群发消息
*
* @param message
* 消息内容
* @param userIds
*/
public static void sendMessage(String message, List<String> ids) {
for (String id : ids) {
public static void sendMessageByUserIds(String message, List<String> userIds) {
for (String id : userIds) {
Session session = clients.get(id);
if(session!=null){
LOGGER.info("服务端给客户端[{}]发送消息{}", session.getId(), message);

View File

@ -35,6 +35,9 @@ public class SysNotice extends BaseEntity
/** 公告状态0正常 1关闭 */
private String status;
/** 公告是否已读0未读 1已读 */
private String isRead;
public Long getNoticeId()
{
return noticeId;
@ -94,6 +97,10 @@ public class SysNotice extends BaseEntity
return status;
}
public String getIsRead() { return isRead; }
public void setIsRead(String isRead) { this.isRead = isRead; }
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -92,14 +92,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inner join sys_user_notice b on a.notice_id = b.noticeId
<where>
and b.userId = #{userId}
and CONVERT(date, create_time) = CONVERT(date, GETDATE())
and CONVERT(date, a.create_time) = CONVERT(date, GETDATE())
and a.status = '0' and a.isRead = '0'
</where>
order by create_time desc
</select>
<insert id="insertNoticeUserBatch" parameterType="java.util.List">
insert into sys_user_notice
(noticeId,userId)
<insert id="insertNoticeUserBatch">
insert into sys_user_notice(noticeId,userId)
values
<foreach collection="list" item="item" index="index" separator=",">
(

View File

@ -7,5 +7,9 @@ ENV = 'development'
# 江南业务系统/开发环境
VUE_APP_BASE_API = '/dev-api'
# 江南业务系统-WebSocket/开发环境
VUE_APP_WEBSOCKET_API = '/websocket-api'
VUE_APP_WSS_WEBSOCKET_API = '/wss-websocket-api'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -6,3 +6,7 @@ ENV = 'production'
# 江南业务系统/生产环境
VUE_APP_BASE_API = '/prod-api'
# 江南业务系统-WebSocket/开发环境
VUE_APP_WEBSOCKET_API = '/websocket-api'
VUE_APP_WSS_WEBSOCKET_API = '/wss-websocket-api'

View File

@ -51,3 +51,12 @@ export function navbarNoticelist(query) {
params: query
})
}
// 导航面板 消息通知 获取详细信息
export function getNavbarNotice(noticeId) {
return request({
url: '/system/notice/navbarNotice/' + noticeId,
method: 'get'
})
}

View File

@ -3,7 +3,7 @@
<el-dropdown>
<span class="el-dropdown-link">
<svg-icon icon-class="message" slot="reference" />
<el-badge :value="noteTotal"></el-badge>
<el-badge :value="noteTotal" v-if="noteTotal>0"></el-badge>
</span>
<el-dropdown-menu slot="dropdown">
@ -12,21 +12,62 @@
<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-tab-pane label="业务通知" name="third">
<el-dropdown-item v-for="(item,index) in businessData" :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-tabs>
</el-dropdown-menu>
<!--<mode-dialog :visible="noteVisible" :noteType="noteType" :noticeId="noticeId" @close="closeMode"></mode-dialog>-->
<el-dialog :title="noteTitle" :visible.sync="noteVisible" width="780px" append-to-body>
<el-form ref="form" :model="form" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="标题" prop="noticeTitle">
<el-input v-model="form.noticeTitle" :disabled="true"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="noticeType">
<el-select v-model="form.noticeType" :disabled="true">
<el-option
v-for="dict in dict.type.sys_notice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="内容">
<editor v-model="form.noticeContent" :min-height="192"/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-dialog>
</el-dropdown>
</template>
<script>
import { navbarNoticelist } from '@/api/system/notice';
import { getNavbarNotice} from "@/api/system/notice";
/*
import ModeDialog from '@/components/ModeDialog'
*/
@ -34,9 +75,7 @@
export default {
name: 'NavbarNotice',
/*
components: { ModeDialog },
*/
dicts: ['sys_notice_type'],
data() {
return {
activeName: 'first',
@ -45,18 +84,25 @@
sysLog: [],
//
noticeData: [],
//
businessData: [],
websock: null,
lockReconnect: false,
heartCheck: null,
//
noteTitle: '',
noteVisible: false,
noteType: 0,
noticeId: 0
//
form: {},
}
},
mounted() {
// WebSocket
this.initWebSocket();
},
created(){
this.getList();
},
destroyed: function() { //
this.websocketOnclose();
},
@ -71,24 +117,42 @@
var sysLog = res[2]?res[2]:[];
this.sysLog = sysLog.slice(0,5);
this.noteTotal = this.noticeData.length+this.sysLog.length;
var businessData = res[3]?res[3]:[];
this.businessData = businessData.slice(0,5);
this.noteTotal = this.noticeData.length+this.sysLog.length+this.businessData.length;
})
},
handleClick(tab, event) {
},
clickNote(data) {
getNavbarNotice(data.noticeId).then(response => {
this.form = response.data;
this.noteTitle = "消息详情"
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.state.user.id;
// WebSocketwshttpwsshttps
var url = 'ws://localhost:3334/websocket/message/'+userId;
// Location
const nowLocation = window.location;
// => httphttps
const protocol = nowLocation.protocol;
// hostName => ip
const hostName = nowLocation.hostname;
// host => ip:port
const host = nowLocation.host;
// websocket api
// 使 ws wss
//const websocket_pattern = (hostName == '') ? 'wss-websocket-api' : 'websocket-api';
const websocket_pattern = 'websocket-api';
// websocket
//const webSocketApiUrl = ((protocol.startsWith('https')) ? 'wss://' : 'ws://') + host + '/' + websocket_pattern;
const webSocketApiUrl = 'ws://' + host + '/' + websocket_pattern;
// WebSocket,
// /websocket/template-push/ websocket
let url = webSocketApiUrl + '/websocket/message/'+userId;
this.websock = new WebSocket(url)
this.websock.onopen = this.websocketOnopen
this.websock.onerror = this.websocketOnerror
@ -113,6 +177,8 @@
this.getList();
Notification({
title: '消息',
duration: 3000,
dangerouslyUseHTMLString: true,
message: JSON.parse(e.data).noticeTitle
})
},
@ -162,7 +228,7 @@
width:300px
}
.el-dropdown-menu{
width:250px
width:300px
}
::v-deep .el-dropdown-menu {
top: 28px;

View File

@ -40,8 +40,16 @@ module.exports = {
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
},
[process.env.VUE_APP_WEBSOCKET_API]: {
target: `http://localhost:3334`,
changeOrigin: true,
ws: true,
pathRewrite: {
['^' + process.env.VUE_APP_WEBSOCKET_API]: ''
}
},
},
disableHostCheck: true
},
css: {