Commit 281406d9 authored by 耿迪迪's avatar 耿迪迪

消息通知

parent c1b6d204
package com.zehong.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;
import com.zehong.common.annotation.Log;
import com.zehong.common.core.controller.BaseController;
import com.zehong.common.core.domain.AjaxResult;
import com.zehong.common.core.domain.entity.SysUser;
import com.zehong.common.core.page.TableDataInfo;
import com.zehong.common.enums.BusinessType;
import com.zehong.common.utils.SecurityUtils;
import com.zehong.common.utils.StringUtils;
import com.zehong.framework.web.service.WebSocketServer;
import com.zehong.system.domain.SysNotice;
import com.zehong.system.service.ISysNoticeService;
import com.zehong.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 公告 信息操作处理
......@@ -33,6 +35,12 @@ public class SysNoticeController extends BaseController
@Autowired
private ISysNoticeService noticeService;
@Autowired
private WebSocketServer webSocketServer;
@Autowired
private ISysUserService sysUserService;
/**
* 获取通知公告列表
*/
......@@ -89,4 +97,40 @@ public class SysNoticeController extends BaseController
{
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
}
/**
* 推送消息
* @param notice 通知消息体
* @return
*/
@PostMapping("/sendNotice")
public AjaxResult sendNotice(@RequestBody SysNotice notice){
notice.setCreateBy(SecurityUtils.getUsername());
notice.setCreateTime(new Date());
if(StringUtils.isNotNull(notice.getUserId())){
//新增通知
noticeService.insertNotice(notice);
//推送通知消息
webSocketServer.sendMessage(String.valueOf(notice.getUserId()));
}
//根据角色推送消息
if(StringUtils.isNotEmpty(notice.getRoles())){
Map<String,Object> map = new HashMap<>();
if(StringUtils.isNotNull(notice.getDeptId())){
map.put("deptId",notice.getDeptId());
}
map.put("roleKey", notice.getRoles());
List<SysUser> userList = sysUserService.selectUserInfoByDeptAndRoleKey(map);
userList.stream().forEach(item ->{
//新增通知
notice.setUserId(item.getUserId());
noticeService.insertNotice(notice);
//推送通知消息
webSocketServer.sendMessage(String.valueOf(item.getUserId()));
});
}
return AjaxResult.success("消息推送成功!");
}
}
package com.zehong.framework.web.domain.server;
import com.zehong.common.core.domain.entity.SysUser;
import javax.websocket.Session;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -17,11 +19,6 @@ public class WebSocketBean {
*/
private Session session;
/**
* 用户id
*/
private Long userId;
/**
* 连接错误次数
*/
......@@ -45,12 +42,4 @@ public class WebSocketBean {
public void setSession(Session session) {
this.session = session;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
}
\ No newline at end of file
......@@ -13,18 +13,16 @@ import org.springframework.util.CollectionUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author geng
* webSocket工具类
*/
@Component
@ServerEndpoint("/webSocket/{roles}/{userId}")
@ServerEndpoint("/webSocket/{userId}")
public class WebSocketServer {
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
......@@ -37,7 +35,7 @@ public class WebSocketServer {
/**
* 用来存放每个客户端对应的webSocket对象。
*/
private static Map<String,List<WebSocketBean>> webSocketInfo;
private static Map<String,WebSocketBean> webSocketInfo;
static
{
......@@ -46,33 +44,18 @@ public class WebSocketServer {
}
@OnOpen
public void onOpen(Session session, @PathParam("roles") String roles, @PathParam("userId") String userId) {
for(String role : roles.split(",")){
WebSocketBean bean = new WebSocketBean();
bean.setSession(session);
bean.setUserId(Long.valueOf(userId));
if(webSocketInfo.containsKey(role)){
List<WebSocketBean> beans = webSocketInfo.get(role);
// 连接成功当前对象放入webSocket对象集合
beans.add(bean);
sendMessage(bean,initNotice(userId));
return;
}
List<WebSocketBean> beans = new ArrayList<>();
beans.add(bean);
webSocketInfo.put(role,beans);
sendMessage(bean,initNotice(userId));
}
public void onOpen(Session session, @PathParam("userId") String userId) {
WebSocketBean bean = new WebSocketBean();
bean.setSession(session);
webSocketInfo.put(userId,bean);
sendMessage(userId,initNotice(userId));
log.info("客户端连接服务器session id :"+session.getId()+",当前连接数:" + webSocketInfo.size());
}
private String initNotice(String userId){
SysNotice notice = new SysNotice();
notice.setUserId(Long.valueOf(userId));
notice.setStatus("0");
ISysNoticeService sysNoticeService = SpringUtils.getBean(ISysNoticeService.class);
List<SysNotice> notices = sysNoticeService.selectNoticeList(notice);
if(CollectionUtils.isEmpty(notices)){
......@@ -84,9 +67,10 @@ public class WebSocketServer {
@OnClose
public void onClose(Session session) {
// 客户端断开连接移除websocket对象
for (Map.Entry<String, List<WebSocketBean>> entry : webSocketInfo.entrySet()) {
List<WebSocketBean> beans = entry.getValue().stream().filter(item ->item.getSession().getId().equals(session.getId())).collect(Collectors.toList());
entry.getValue().removeAll(beans);
for (Map.Entry<String, WebSocketBean> entry : webSocketInfo.entrySet()) {
if(session.getId().equals(entry.getValue().getSession().getId())){
webSocketInfo.remove(entry.getKey());
}
}
log.info("客户端断开连接,当前连接数:" + webSocketInfo.size());
}
......@@ -109,35 +93,22 @@ public class WebSocketServer {
}
/**
* 查找发送消息用户
* @param role 角色
* @param userId 用户id
* @param message 消息体
* 根据userId 推送用户信息
* @param userId
*/
public void findMessageUser(String role,Long userId, String message) {
List<WebSocketBean> beans = webSocketInfo.get(role);
if(!CollectionUtils.isEmpty(beans)){
//发送给指定角色
if(null == userId){
beans.forEach(item ->{
sendMessage(item,message);
});
return;
}
//发送给指定用户
List<WebSocketBean> userBean = beans.stream().filter(item -> item.getUserId().equals(userId)).collect(Collectors.toList());
userBean.stream().forEach(item -> {
sendMessage(item,message);
});
}
public void sendMessage(String userId){
sendMessage(userId,initNotice(userId));
}
/**
* 发送消息
* @param bean webSocket对象
* @param userId 用户id
* @param message 消息体
*/
private void sendMessage(WebSocketBean bean, String message) {
public void sendMessage(String userId, String message) {
WebSocketBean bean = webSocketInfo.get(userId);
if(bean == null) return;
try{
// 发送消息
bean.getSession().getBasicRemote().sendText(message);
......@@ -149,7 +120,7 @@ public class WebSocketServer {
int errorNum = bean.getErroerLinkCount();
// 小于最大重试次数重发
if(errorNum <= MAX_ERROR_NUM){
sendMessage(bean, message);
sendMessage(userId, message);
}else{
log.error("发送消息失败超过最大次数");
// 清空错误计数
......
......@@ -38,6 +38,16 @@ public class SysNotice extends BaseEntity
@Excel(name = "公告状态", readConverterExp = "0=正常,1=关闭")
private String status;
/**
* 部门
*/
private Long deptId;
/**
* 角色
*/
private String roles;
public void setNoticeId(Integer noticeId)
{
this.noticeId = noticeId;
......@@ -93,6 +103,22 @@ public class SysNotice extends BaseEntity
return status;
}
public Long getDeptId() {
return deptId;
}
public void setDeptId(Long deptId) {
this.deptId = deptId;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
......
package com.zehong.system.mapper;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
import com.zehong.common.core.domain.entity.SysUser;
......@@ -115,4 +117,6 @@ public interface SysUserMapper
* @return
*/
List<SysUser> selectTransactorByDeptId(Long deptId);
List<SysUser> selectUserInfoByDeptAndRoleKey(Map<String,Object> map);
}
package com.zehong.system.service;
import java.util.List;
import java.util.Map;
import com.zehong.common.core.domain.entity.SysUser;
/**
......@@ -171,4 +173,6 @@ public interface ISysUserService
* @return
*/
List<SysUser> selectTransactorByDeptId(Long deptId);
List<SysUser> selectUserInfoByDeptAndRoleKey(Map<String,Object> map);
}
......@@ -2,6 +2,8 @@ package com.zehong.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -469,4 +471,8 @@ public class SysUserServiceImpl implements ISysUserService
public List<SysUser> selectTransactorByDeptId(Long deptId){
return userMapper.selectTransactorByDeptId(deptId);
}
public List<SysUser> selectUserInfoByDeptAndRoleKey(Map<String,Object> map){
return userMapper.selectUserInfoByDeptAndRoleKey(map);
}
}
......@@ -154,8 +154,10 @@ public class TDebitCreditServiceImpl implements ITDebitCreditService
*/
@Transactional(rollbackFor = Exception.class)
public int settlementDebitCredit(TDebitCredit tDebitCredit){
//结算
settlementDebit.settlementDebit(tDebitCredit);
if("2".equals(tDebitCredit.getDebitStatus())){
//结算
settlementDebit.settlementDebit(tDebitCredit);
}
tDebitCredit.setUpdateTime(DateUtils.getNowDate());
return tDebitCreditMapper.updateTDebitCredit(tDebitCredit);
}
......
......@@ -162,8 +162,10 @@ public class TTradeProjectServiceImpl implements ITTradeProjectService
@Transactional(rollbackFor = Exception.class)
public int settlementTrade(TTradeProject tTradeProject){
TTradeProject tradeInfo = tTradeProjectMapper.selectTTradeProjectById(tTradeProject.getTradeId());
//交易结算
settlementTrade.settleAbleAmount(tradeInfo);
if("3".equals(tTradeProject.getTradeStatus())){
//交易结算
settlementTrade.settleAbleAmount(tradeInfo);
}
tradeInfo.setTradeStatus(tTradeProject.getTradeStatus());
tradeInfo.setApplyDeptManagerId(tTradeProject.getApplyDeptManagerId());
tradeInfo.setSettlementTime(new Date());
......
......@@ -31,6 +31,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="userId != null "> and user_id = #{userId}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
</where>
ORDER BY create_time DESC
</select>
<select id="selectNoticeById" parameterType="Integer" resultMap="SysNoticeResult">
......
......@@ -184,4 +184,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where u.dept_id = #{deptId} AND r.role_key = "transactor";
</select>
<select id="selectUserInfoByDeptAndRoleKey" parameterType="Map" resultMap="SysUserResult">
<include refid="selectUserVo"/>
<where>
<if test="deptId != null">
AND u.dept_id = #{deptId}
</if>
<if test="roleKey != null">
AND r.role_key = #{roleKey}
</if>
</where>
</select>
</mapper>
......@@ -6,3 +6,6 @@ VUE_APP_BASE_API = '/dev-api'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
# websocket地址
VUE_APP_WEBSOCKET_URL = 'ws://localhost:8668/precisionEffect/webSocket/'
......@@ -3,3 +3,6 @@ ENV = 'production'
# 泽宏精效管理系统/生产环境
VUE_APP_BASE_API = '/prod-api'
# websocket地址
VUE_APP_WEBSOCKET_URL = 'ws://localhost:8668/precisionEffect/webSocket/'
......@@ -41,4 +41,13 @@ export function delNotice(noticeId) {
url: '/system/notice/' + noticeId,
method: 'delete'
})
}
\ No newline at end of file
}
//推送消息
export function sendNotice(data) {
return request({
url: '/system/notice/sendNotice',
method: 'post',
data: data
})
}
<template>
<div class="instantMessage">
<el-dropdown trigger="click" :popper-append-to-body="false" style="height: 30px">
<el-dropdown ref="dropDown" trigger="click" :popper-append-to-body="false" :hide-on-click="false" style="height: 30px">
<div>
<el-badge :value= "this.msgInfo.length>0 ? this.msgInfo.length : ''" :max="99" class="messageMark">
......@@ -15,21 +15,33 @@
</el-dropdown-item>
<div v-if="this.msgInfo.length > 0">
<el-row>
<el-col :span="12">
<el-col :span="6">
<el-dropdown-item>标题</el-dropdown-item>
</el-col>
<el-col :span="12">
<el-col :span="6">
<el-dropdown-item>内容</el-dropdown-item>
</el-col>
<el-col :span="6">
<el-dropdown-item>类型</el-dropdown-item>
</el-col>
<el-col :span="6">
<el-dropdown-item>标记</el-dropdown-item>
</el-col>
</el-row>
<el-row v-for="item in msgInfo">
<el-col :span="12">
<el-col :span="6">
<el-dropdown-item class="region-item-style">{{ item.noticeTitle }}</el-dropdown-item>
</el-col>
<el-col :span="12">
<el-col :span="6">
<el-dropdown-item class="region-item-style" v-text="item.noticeTitle" />
</el-col>
<el-col :span="6">
<el-dropdown-item v-if="item.noticeType == '1'">通知</el-dropdown-item>
<el-dropdown-item v-if="item.noticeType == '2'">公告</el-dropdown-item>
</el-col>
<el-col :span="6">
<el-dropdown-item><el-button type="text" @click="isRead(item.noticeId)">已读</el-button></el-dropdown-item>
</el-col>
</el-row>
</div>
</el-dropdown-menu>
......@@ -39,7 +51,7 @@
</template>
<script>
import { updateNotice } from "@/api/system/notice"
export default {
name: "message",
data(){
......@@ -50,16 +62,34 @@
created(){
//登录成功后创建websocket
if(!this.$websocket.isExsitWebsocket()){
this.$websocket.initWebSocket("ws://36.139.131.221:8668/precisionEffect/webSocket/" + this.$store.state.user.roles.join(",") + "/" + this.$store.state.user.userId);
this.$websocket.initWebSocket(process.env.VUE_APP_WEBSOCKET_URL + this.$store.state.user.userId);
this.$websocket.addEvent("onmessage",(msg) =>{
if(msg.data){
console.log("您有新的消息请注意接收:", JSON.parse(msg.data));
this.msgInfo = JSON.parse(msg.data);
this.$refs.dropDown.visible = false;
/* let msgData = JSON.parse(msg.data);
if(msgData instanceof Array){
this.msgInfo = msgData;
}else{
this.msgInfo.push(msgData);
}*/
}
});
}
},
methods:{
isRead(noticeId){
updateNotice({noticeId:noticeId,status:"1"}).then(res =>{
if(res.code == 200){
this.$message.success("标记成功");
this.msgInfo.splice(this.msgInfo.findIndex(item =>item.noticeId == noticeId),1);
this.$refs.dropDown.visible = false;
}else{
this.$message.error("标记失败")
}
})
}
}
......
......@@ -20,6 +20,7 @@
import confirm from "./Confirm";
import calculate from "./Calculate";
import repay from "./Repay"
import { sendNotice } from "@/api/system/notice";
export default {
name: "operator-button",
components:{
......@@ -80,6 +81,9 @@
}
if(this.debitData.debitStatus == "1"){
settlementDebitCredit(this.$refs.currentCom.submitSuggestion()).then(res =>{
if(this.$refs.currentCom.submitSuggestion().debitStatus == '4'){
sendNotice({noticeTitle:"您的借贷申请被驳回",noticeType:"1",noticeContent:"您的借贷申请被驳回",userId:this.debitInfo.operatorId});
}
this.dealResponse(res);
})
return;
......@@ -93,6 +97,7 @@
}
updateCredit(this.$refs.currentCom.submitSuggestion()).then(res =>{
this.dealResponse(res);
sendNotice({noticeTitle:"您有新借贷待审核",noticeType:"1",noticeContent:"您有新借贷待审核",roles:"calculator"})
})
},
......@@ -105,7 +110,7 @@
}else{
this.$message.error("提交失败!");
}
}
},
}
}
</script>
......
......@@ -217,8 +217,8 @@
<el-form-item label="计息日" prop="sumInterestDate">
<el-date-picker clearable size="small"
v-model="form.sumInterestDate"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择计息日"
style="width: 100%">
</el-date-picker>
......@@ -228,8 +228,8 @@
<el-form-item label="预计还款日" prop="expectedRepaymentDate">
<el-date-picker clearable size="small"
v-model="form.expectedRepaymentDate"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择预计还款日"
style="width: 100%">
</el-date-picker>
......@@ -268,6 +268,7 @@ import { treeselect } from "@/api/system/dept";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import TableList from "./components/TableList";
import { sendNotice } from "@/api/system/notice";
export default {
name: "Credit",
components: {
......@@ -466,11 +467,17 @@ export default {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
this.noticeNext();
});
}
}
});
},
//通知下一个人
noticeNext(){
sendNotice({noticeTitle:"您有新借贷待确认",noticeType:"1",noticeContent:"您有新借贷待确认",
deptId:this.form.lendDeptId,roles:"deptLeader"})
},
/** 删除按钮操作 */
handleDelete(row) {
const debitIds = row.debitId || this.ids;
......
......@@ -16,6 +16,7 @@
import calculate from "./Calculate";
import confirm from "./Confirm";
import purchaseDetail from "./PurchaseDetail";
import { sendNotice } from "@/api/system/notice";
export default {
name: "operator-button",
components:{
......@@ -78,6 +79,9 @@
this.open = false;
this.$emit("getList");
this.$message.success("审核成功!");
if(this.$refs.currentCom.submitSuggestion().purchaseStatus == '3'){
sendNotice({noticeTitle:"您的采购申请被驳回",noticeType:"1",noticeContent:"您的采购申请被驳回",userId:this.purchaseInfo.handledByUserId});
}
}else{
this.$message.error("审核失败!");
}
......@@ -90,11 +94,12 @@
this.open = false;
this.$emit("getList");
this.$message.success("提交成功!");
sendNotice({noticeTitle:"您有新采购信息待审批",noticeType:"1",noticeContent:"您有新采购信息待审批",roles:"calculator"})
}else{
this.$message.error("提交失败!");
}
})
}
},
}
}
</script>
......
......@@ -283,6 +283,7 @@
import { listPurchase, getPurchase, delPurchase, addPurchase, updatePurchase, exportPurchase } from "@/api/transaction/purchase";
import { selectTransactorByDeptId } from "@/api/system/user";
import OperatorButton from "./components/OperatorButton";
import { sendNotice } from "@/api/system/notice";
export default {
name: "Purchase",
components: {
......@@ -366,7 +367,6 @@ export default {
this.getList();
this.getUsers();
this.getPurchaseStatusList();
console.log("fdsfdsfdsf0-----------------",this.$store.state.user.userId)
},
methods: {
getPurchaseStatusList(){
......@@ -494,11 +494,17 @@ export default {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
this.noticeNext();
});
}
}
});
},
//通知下一个人
noticeNext(){
sendNotice({noticeTitle:"您有新采购信息待确认",noticeType:"1",noticeContent:"您有新采购信息待确认",
deptId:this.$store.state.user.deptId,roles:"deptLeader"})
},
/** 删除按钮操作 */
handleDelete(row) {
const purchaseIds = row.purchaseId || this.ids;
......
......@@ -17,6 +17,7 @@
import evaluate from "./Evaluate";
import confirm from "./Confirm";
import approval from "./Approval";
import { sendNotice } from "@/api/system/notice";
export default {
name: "operator-button",
components:{
......@@ -81,6 +82,9 @@
this.open = false;
this.$emit("getList");
this.$message.success("复核成功!");
if(this.$refs.currentCom.submitSuggestion().tradeStatus == "4"){
sendNotice({noticeTitle:"您有新交易项目被驳回",noticeType:"1",noticeContent:"您有新交易项目被驳回",userId:this.tradeInfo.applyId})
}
}else{
this.$message.error("复核失败!");
}
......@@ -93,6 +97,17 @@
this.open = false;
this.$emit("getList");
that.$message.success("提交成功!");
console.log("fdsfdsf---",this.$refs.currentCom.submitSuggestion().tradeStatus)
if(this.$refs.currentCom.submitSuggestion().tradeStatus == "1"){
sendNotice({noticeTitle:"您有新交易项目待确认",noticeType:"1",noticeContent:"您有新交易项目待确认",
deptId:this.tradeInfo.tradeDeptId,roles:"deptLeader"})
}
if(this.$refs.currentCom.submitSuggestion().tradeStatus == "2"){
sendNotice({noticeTitle:"您有新交易项目待确认",noticeType:"1",noticeContent:"您有新交易项目待确认",
deptId:this.tradeInfo.applyDeptId,roles:"deptLeader"})
}
}else{
that.$message.error("提交失败!");
}
......
......@@ -328,6 +328,7 @@ import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import FileUpload from "@/components/FileUpload";
import uploadfile from "@/assets/uploadfile.png";
import TableList from "./components/TableList";
import { sendNotice } from "@/api/system/notice";
export default {
name: "Project",
components: {
......@@ -519,6 +520,7 @@ export default {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
sendNotice({noticeTitle:"您有新交易项目待评价",noticeType:"1",noticeContent:"您有新交易项目待评价",userId:this.form.tradeTransactor})
});
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment