Commit 09e21d47 authored by 夏敏伟's avatar 夏敏伟

增加聊天室功能

parent a5858bbc
import { get, post, addParam } from "../util/http_util"; import { get, post, addParam } from "../../util/http_util";
const PREFIX_RECORDS = 'api/rest/chat/chatRecords'; const PREFIX_RECORDS = 'api/rest/chat/chatRecords';
//分页查询群聊记录 //分页查询群聊记录
export const getRecordsByPaging = (chatRoomId, currPage, pageSize, startTime, endTime, fromUserId) => { export const getRecordsByPaging = (chatRoomId, currPage, pageSize, startTime, endTime, fromUserId,teamId) => {
let url = `${PREFIX_CHATROOM}/chatRecords/page`; let url = `${PREFIX_RECORDS}/chatroom/page`;
url += addParam({ chatRoomId, currPage, pageSize, startTime, endTime, fromUserId }); url += addParam({ chatRoomId, currPage, pageSize, startTime, endTime, fromUserId,teamId });
return get(url); return get(url);
} }
//分页查询私信信息 //分页查询私信信息
export const getPrivateLetterByPaging = (currPage, pageSize, startTime, endTime, userId1, userId2) => { export const getPrivateLetterByPaging = (currPage, pageSize, startTime, endTime, userId1, userId2) => {
let url = `${PREFIX_CHATROOM}/chatRecords/direct`; let url = `${PREFIX_RECORDS}/direct`;
url += addParam({ currPage, pageSize, startTime, endTime, userId1, userId2 }); url += addParam({ currPage, pageSize, startTime, endTime, userId1, userId2 });
return get(url); return get(url);
} }
//查询群聊中未读信息 //查询群聊中未读信息
export const getListUnread = (chatRoomId, userId) => { export const getListUnread = (chatRoomId, userId) => {
return get(`${PREFIX_RECORDS}/chatRecords/listUnread?chatRoomId=${chatRoomId}&userId=${userId}`); return get(`${PREFIX_RECORDS}/listUnread?chatRoomId=${chatRoomId}&userId=${userId}`);
} }
\ No newline at end of file
...@@ -13,8 +13,8 @@ export const createChatRoom = data => { ...@@ -13,8 +13,8 @@ export const createChatRoom = data => {
} }
//查询某个聊天室(群组)详情信息 //查询某个聊天室(群组)详情信息
export const getChatRoomInfo = id => { export const getChatRoomInfo = (id,userId) => {
return get(`${PREFIX_CHATROOM}/info?id=${id}`); return get(`${PREFIX_CHATROOM}/info?id=${id}&userId=${userId}`);
} }
//加入聊天室(群组) //加入聊天室(群组)
......
// Generated by CoffeeScript 1.7.1
/*
Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0
Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/)
Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com)
*/
(function(){var t,e,n,i,r={}.hasOwnProperty,o=[].slice;t={LF:"\n",NULL:"\x00"};n=function(){var e;function n(t,e,n){this.command=t;this.headers=e!=null?e:{};this.body=n!=null?n:""}n.prototype.toString=function(){var e,i,o,s,u;e=[this.command];o=this.headers["content-length"]===false?true:false;if(o){delete this.headers["content-length"]}u=this.headers;for(i in u){if(!r.call(u,i))continue;s=u[i];e.push(""+i+":"+s)}if(this.body&&!o){e.push("content-length:"+n.sizeOfUTF8(this.body))}e.push(t.LF+this.body);return e.join(t.LF)};n.sizeOfUTF8=function(t){if(t){return encodeURI(t).match(/%..|./g).length}else{return 0}};e=function(e){var i,r,o,s,u,a,c,f,h,l,p,d,g,b,m,v,y;s=e.search(RegExp(""+t.LF+t.LF));u=e.substring(0,s).split(t.LF);o=u.shift();a={};d=function(t){return t.replace(/^\s+|\s+$/g,"")};v=u.reverse();for(g=0,m=v.length;g<m;g++){l=v[g];f=l.indexOf(":");a[d(l.substring(0,f))]=d(l.substring(f+1))}i="";p=s+2;if(a["content-length"]){h=parseInt(a["content-length"]);i=(""+e).substring(p,p+h)}else{r=null;for(c=b=p,y=e.length;p<=y?b<y:b>y;c=p<=y?++b:--b){r=e.charAt(c);if(r===t.NULL){break}i+=r}}return new n(o,a,i)};n.unmarshall=function(n){var i;return function(){var r,o,s,u;s=n.split(RegExp(""+t.NULL+t.LF+"*"));u=[];for(r=0,o=s.length;r<o;r++){i=s[r];if((i!=null?i.length:void 0)>0){u.push(e(i))}}return u}()};n.marshall=function(e,i,r){var o;o=new n(e,i,r);return o.toString()+t.NULL};return n}();e=function(){var e;function r(t){this.ws=t;this.ws.binaryType="arraybuffer";this.counter=0;this.connected=false;this.heartbeat={outgoing:1e4,incoming:1e4};this.maxWebSocketFrameSize=16*1024;this.subscriptions={}}r.prototype.debug=function(t){var e;return typeof window!=="undefined"&&window!==null?(e=window.console)!=null?e.log(t):void 0:void 0};e=function(){if(Date.now){return Date.now()}else{return(new Date).valueOf}};r.prototype._transmit=function(t,e,i){var r;r=n.marshall(t,e,i);if(typeof this.debug==="function"){this.debug(">>> "+r)}while(true){if(r.length>this.maxWebSocketFrameSize){this.ws.send(r.substring(0,this.maxWebSocketFrameSize));r=r.substring(this.maxWebSocketFrameSize);if(typeof this.debug==="function"){this.debug("remaining = "+r.length)}}else{return this.ws.send(r)}}};r.prototype._setupHeartbeat=function(n){var r,o,s,u,a,c;if((a=n.version)!==i.VERSIONS.V1_1&&a!==i.VERSIONS.V1_2){return}c=function(){var t,e,i,r;i=n["heart-beat"].split(",");r=[];for(t=0,e=i.length;t<e;t++){u=i[t];r.push(parseInt(u))}return r}(),o=c[0],r=c[1];if(!(this.heartbeat.outgoing===0||r===0)){s=Math.max(this.heartbeat.outgoing,r);if(typeof this.debug==="function"){this.debug("send PING every "+s+"ms")}this.pinger=i.setInterval(s,function(e){return function(){e.ws.send(t.LF);return typeof e.debug==="function"?e.debug(">>> PING"):void 0}}(this))}if(!(this.heartbeat.incoming===0||o===0)){s=Math.max(this.heartbeat.incoming,o);if(typeof this.debug==="function"){this.debug("check PONG every "+s+"ms")}return this.ponger=i.setInterval(s,function(t){return function(){var n;n=e()-t.serverActivity;if(n>s*2){if(typeof t.debug==="function"){t.debug("did not receive server activity for the last "+n+"ms")}return t.ws.close()}}}(this))}};r.prototype._parseConnect=function(){var t,e,n,i;t=1<=arguments.length?o.call(arguments,0):[];i={};switch(t.length){case 2:i=t[0],e=t[1];break;case 3:if(t[1]instanceof Function){i=t[0],e=t[1],n=t[2]}else{i.login=t[0],i.passcode=t[1],e=t[2]}break;case 4:i.login=t[0],i.passcode=t[1],e=t[2],n=t[3];break;default:i.login=t[0],i.passcode=t[1],e=t[2],n=t[3],i.host=t[4]}return[i,e,n]};r.prototype.connect=function(){var r,s,u,a;r=1<=arguments.length?o.call(arguments,0):[];a=this._parseConnect.apply(this,r);u=a[0],this.connectCallback=a[1],s=a[2];if(typeof this.debug==="function"){this.debug("Opening Web Socket...")}this.ws.onmessage=function(i){return function(r){var o,u,a,c,f,h,l,p,d,g,b,m;c=typeof ArrayBuffer!=="undefined"&&r.data instanceof ArrayBuffer?(o=new Uint8Array(r.data),typeof i.debug==="function"?i.debug("--- got data length: "+o.length):void 0,function(){var t,e,n;n=[];for(t=0,e=o.length;t<e;t++){u=o[t];n.push(String.fromCharCode(u))}return n}().join("")):r.data;i.serverActivity=e();if(c===t.LF){if(typeof i.debug==="function"){i.debug("<<< PONG")}return}if(typeof i.debug==="function"){i.debug("<<< "+c)}b=n.unmarshall(c);m=[];for(d=0,g=b.length;d<g;d++){f=b[d];switch(f.command){case"CONNECTED":if(typeof i.debug==="function"){i.debug("connected to server "+f.headers.server)}i.connected=true;i._setupHeartbeat(f.headers);m.push(typeof i.connectCallback==="function"?i.connectCallback(f):void 0);break;case"MESSAGE":p=f.headers.subscription;l=i.subscriptions[p]||i.onreceive;if(l){a=i;h=f.headers["message-id"];f.ack=function(t){if(t==null){t={}}return a.ack(h,p,t)};f.nack=function(t){if(t==null){t={}}return a.nack(h,p,t)};m.push(l(f))}else{m.push(typeof i.debug==="function"?i.debug("Unhandled received MESSAGE: "+f):void 0)}break;case"RECEIPT":m.push(typeof i.onreceipt==="function"?i.onreceipt(f):void 0);break;case"ERROR":m.push(typeof s==="function"?s(f):void 0);break;default:m.push(typeof i.debug==="function"?i.debug("Unhandled frame: "+f):void 0)}}return m}}(this);this.ws.onclose=function(t){return function(){var e;e="Whoops! Lost connection to "+t.ws.url;if(typeof t.debug==="function"){t.debug(e)}t._cleanUp();return typeof s==="function"?s(e):void 0}}(this);return this.ws.onopen=function(t){return function(){if(typeof t.debug==="function"){t.debug("Web Socket Opened...")}u["accept-version"]=i.VERSIONS.supportedVersions();u["heart-beat"]=[t.heartbeat.outgoing,t.heartbeat.incoming].join(",");return t._transmit("CONNECT",u)}}(this)};r.prototype.disconnect=function(t,e){if(e==null){e={}}this._transmit("DISCONNECT",e);this.ws.onclose=null;this.ws.close();this._cleanUp();return typeof t==="function"?t():void 0};r.prototype._cleanUp=function(){this.connected=false;if(this.pinger){i.clearInterval(this.pinger)}if(this.ponger){return i.clearInterval(this.ponger)}};r.prototype.send=function(t,e,n){if(e==null){e={}}if(n==null){n=""}e.destination=t;return this._transmit("SEND",e,n)};r.prototype.subscribe=function(t,e,n){var i;if(n==null){n={}}if(!n.id){n.id="sub-"+this.counter++}n.destination=t;this.subscriptions[n.id]=e;this._transmit("SUBSCRIBE",n);i=this;return{id:n.id,unsubscribe:function(){return i.unsubscribe(n.id)}}};r.prototype.unsubscribe=function(t){delete this.subscriptions[t];return this._transmit("UNSUBSCRIBE",{id:t})};r.prototype.begin=function(t){var e,n;n=t||"tx-"+this.counter++;this._transmit("BEGIN",{transaction:n});e=this;return{id:n,commit:function(){return e.commit(n)},abort:function(){return e.abort(n)}}};r.prototype.commit=function(t){return this._transmit("COMMIT",{transaction:t})};r.prototype.abort=function(t){return this._transmit("ABORT",{transaction:t})};r.prototype.ack=function(t,e,n){if(n==null){n={}}n["message-id"]=t;n.subscription=e;return this._transmit("ACK",n)};r.prototype.nack=function(t,e,n){if(n==null){n={}}n["message-id"]=t;n.subscription=e;return this._transmit("NACK",n)};return r}();i={VERSIONS:{V1_0:"1.0",V1_1:"1.1",V1_2:"1.2",supportedVersions:function(){return"1.1,1.0"}},client:function(t,n){var r,o;if(n==null){n=["v10.stomp","v11.stomp"]}r=i.WebSocketClass||WebSocket;o=new r(t,n);return new e(o)},over:function(t){return new e(t)},Frame:n};if(typeof exports!=="undefined"&&exports!==null){exports.Stomp=i}if(typeof window!=="undefined"&&window!==null){i.setInterval=function(t,e){return window.setInterval(e,t)};i.clearInterval=function(t){return window.clearInterval(t)};window.Stomp=i}else if(!exports){self.Stomp=i}}).call(this);
\ No newline at end of file
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
</div> </div>
<div id="chatContent" class="chatContent"> <div id="chatContent" class="chatContent">
<div v-for="item in chatMessageList" class="everyMessage"> <div v-for="item in chatMessageList" class="everyMessage">
<div v-for="item1 in item.list" :style="{ justifyContent: item.isMe ? 'flex-end' : 'flex-start' }"> <div :style="{ justifyContent: item.fromUserId == userInfo.account ? 'flex-end' : 'flex-start' }">
<template v-if="!item.isMe"> <template v-if="item.fromUserId != userInfo.account">
<img :src="avatar" alt=""> <img :src="avatar" alt="">
<div v-text="item1" style="background-color:white"></div> <div v-text="item.content" style="background-color:white"></div>
</template> </template>
<template v-else-if="item.isMe"> <template v-else-if="item.fromUserId == userInfo.account">
<div v-text="item1" style="background-color: #85ce61;"></div> <div v-text="item.content" style="background-color: #85ce61;"></div>
<img :src="avatar" alt=""> <img :src="avatar" alt="">
</template> </template>
</div> </div>
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
</el-input> </el-input>
</div> </div>
<div class="sendMessageButtonList"> <div class="sendMessageButtonList">
<el-button size="mini" type="info" @click="sendNotice">发送公告</el-button>
<el-button size="mini" type="info" @click="test">邮箱</el-button>
<el-button size="mini" type="success" @click="sendMessageFn">发送</el-button> <el-button size="mini" type="success" @click="sendMessageFn">发送</el-button>
</div> </div>
</div> </div>
...@@ -45,6 +43,8 @@ ...@@ -45,6 +43,8 @@
<script> <script>
import avatar from '../../../assets/img/ddkz/headPhoto.jpg'; import avatar from '../../../assets/img/ddkz/headPhoto.jpg';
import '../../../util/stomp.min.js'
import { getRecordsByPaging } from '../../../api/chat/chatRecords';
export default { export default {
data() { data() {
return { return {
...@@ -54,26 +54,108 @@ export default { ...@@ -54,26 +54,108 @@ export default {
name: '', name: '',
isLine: undefined isLine: undefined
}, },
chatMessageList: [ sendMessage: '',
{ id: 1, name: 'xxx', isMe: false, list: ['会议主题是xxx', '主要强调两个方面'] }, chatMessageList: [],
{ id: 2, name: 'summer', isMe: true, list: ['确定主题', '同意'] }, stompClient: '',
{ id: 1, name: 'xxx', isMe: false, list: ['会议主题是xxx', '主要强调两个方面'] }, ws: null,
{ id: 2, name: 'summer', isMe: true, list: ['确定主题', '同意'] }, analogDataList: [],
{ id: 1, name: 'xxx', isMe: false, list: ['会议主题是xxx', '主要强调两个方面'] }, currentChatRoom: {}
{ id: 2, name: 'summer', isMe: true, list: ['确定主题', '同意'] }
],
} }
}, },
props: { props: {
visible: Boolean visible: Boolean,
analogData: Array,
currentChatRoomInfo: Object
}, },
methods: { methods: {
handleClose() { handleClose() {
this.$emit('handleCancel'); this.$emit('handleCancel');
},
sendMessageFn() {
if (this.sendMessage.trim().length > 0) {
this.stompClient.send("/app/sendToChatRoomTeam/" + this.currentChatRoom.id + '/' + this.currentChatRoom.teamId, {}, JSON.stringify({
'content': this.sendMessage
}));
setTimeout(() => {
this.keepBottom();
this.sendMessage = '';
}, 100);
} else {
this.$message.warning('不能发送空白信息');
}
},
keepBottom() {
const divscll = document.getElementById('chatContent');
divscll.scrollTop = divscll.scrollHeight;
},
connect() {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(`ws://192.168.168.110:8081/websocket/my-websocket`);
this.stompClient && this.stompClient.connected && this.stompClient.disconnect();
this.stompClient = Stomp.over(this.ws);
this.stompClient.heartbeat.outgoing = 20000; //若使用STOMP 1.1 版本,默认开启了心跳检测机制(默认值都是10000ms)
this.stompClient.heartbeat.incoming = 0; //客户端不从服务端接收心跳包
this.stompClient.connect({ name: this.userInfo.account }, frame => {
this.listChatroom(this.analogDataList);
resolve("连接成功")
}, err => {
console.log(typeof err == "string" ? err : err.headers.message)
reject(typeof err == "string" ? err : err.headers.message)
});
})
},
listChatroom(data) {
//取消群聊的订阅
for (const sub in this.stompClient.subscriptions) {
if (sub.startsWith("multicast")) {
this.stompClient.unsubscribe(sub);
}
}
data.forEach(e => {
//订阅聊天室主题,订阅功能中设置ID:
this.stompClient.subscribe('/topic/multicast/' + e.id, data => {
debugger
}, { id: "multicast" + e.id + new Date().getTime() });
this.stompClient.subscribe('/topic/multicast/' + e.id + '/' + e.teamId, data => {
this.chatMessageList.push({
content: JSON.parse(data.body).content,
fromUserId: data.headers.fromUserId
});
}, { id: "multicast" + e.id + new Date().getTime() });
})
},
getCurrentMessageList(item) {
//查询我方聊天记录
getRecordsByPaging(item.id, 1, 100, '2020-01-01 00:00:00', '2023-10-01 00:00:00', null, item.teamId).then(res1 => {
this.chatMessageList = res1.records;
})
}
},
computed: {
userInfo() {
if (this.$store.getters.userInfo) {
return this.$store.getters.userInfo;
} else {
return { account: "" };
}
} }
}, },
mounted() { mounted() {
this.dialogVisible = this.$props.visible; this.dialogVisible = this.$props.visible;
this.analogDataList = this.$props.analogData;
this.currentChatRoom = this.$props.currentChatRoomInfo;
this.connect();
this.getCurrentMessageList(this.$props.currentChatRoomInfo);
setTimeout(() => {
this.keepBottom();
}, 2000);
} }
} }
</script> </script>
...@@ -162,6 +244,7 @@ export default { ...@@ -162,6 +244,7 @@ export default {
} }
&>div { &>div {
max-width: 50%;
padding: 5px 10px; padding: 5px 10px;
border-radius: 5px; border-radius: 5px;
color: black; color: black;
......
...@@ -7,10 +7,7 @@ ...@@ -7,10 +7,7 @@
</div> --> </div> -->
<div class="personInfo-content"> <div class="personInfo-content">
<div v-for="item in personList" class="everyPersonList"> <div v-for="item in personList" class="everyPersonList">
<span v-for="item1 in item" @click="selectPerson(item1);"> <span v-text="item.userId" @click="selectPerson(item);"></span>
<span v-text="item1.name"></span>
<span :style="{ backgroundColor: item1.isLine ? '#30d64d' : '#686a6b' }"></span>&nbsp;
</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -23,50 +20,12 @@ export default { ...@@ -23,50 +20,12 @@ export default {
data() { data() {
return { return {
dialogVisible: false, dialogVisible: false,
personList: [[ personList: []
{
name: '部长 李叔',
isLine: true
},
{
name: '副部长 李文',
isLine: false
},
{
name: '助理 李叔文',
isLine: true
}
], [
{
name: '部长 李叔',
isLine: false
},
{
name: '副部长 李文',
isLine: true
},
{
name: '助理 李叔文',
isLine: true
}
], [
{
name: '部长 李叔',
isLine: true
},
{
name: '副部长 李文',
isLine: false
},
{
name: '助理 李叔文',
isLine: false
}
]],
} }
}, },
props: { props: {
visible: Boolean visible: Boolean,
peopleList: Array
}, },
methods: { methods: {
handleClose() { handleClose() {
...@@ -75,6 +34,7 @@ export default { ...@@ -75,6 +34,7 @@ export default {
}, },
mounted() { mounted() {
this.dialogVisible = this.$props.visible; this.dialogVisible = this.$props.visible;
this.personList = this.$props.peopleList;
} }
} }
</script> </script>
...@@ -112,7 +72,7 @@ export default { ...@@ -112,7 +72,7 @@ export default {
height: 35px; height: 35px;
line-height: 35px; line-height: 35px;
margin-top: 10px; margin-top: 10px;
padding: 0px 10px; padding: 0px 50px;
font-size: 13px; font-size: 13px;
color: #f1f1f7; color: #f1f1f7;
box-sizing: border-box; box-sizing: border-box;
......
...@@ -63,6 +63,9 @@ export default { ...@@ -63,6 +63,9 @@ export default {
.el-dialog__header { .el-dialog__header {
text-align: center; text-align: center;
.el-dialog__headerbtn{
top: 40px;
}
} }
.el-textarea__inner { .el-textarea__inner {
......
This diff is collapsed.
...@@ -231,7 +231,6 @@ export default { ...@@ -231,7 +231,6 @@ export default {
}) })
} }
}); });
debugger
this.manager_module = this.$store.state.navList[0].children.filter( this.manager_module = this.$store.state.navList[0].children.filter(
(e) => e.meta.type == "1" (e) => e.meta.type == "1"
); );
......
...@@ -86,7 +86,7 @@ module.exports = { ...@@ -86,7 +86,7 @@ module.exports = {
//后台代理 //后台代理
proxy: { proxy: {
'/api/': { '/api/': {
target: 'http://192.168.168.110:8081', target: 'http://192.168.168.106:8081',
ws: true, ws: true,
secure: false, secure: false,
changeOrigin: true, changeOrigin: true,
......
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