diff --git a/commom/src/main/java/com/bx/common/contant/Constant.java b/commom/src/main/java/com/bx/common/contant/Constant.java index 40d3cf7..8e6b2dd 100644 --- a/commom/src/main/java/com/bx/common/contant/Constant.java +++ b/commom/src/main/java/com/bx/common/contant/Constant.java @@ -10,4 +10,6 @@ public class Constant { public static final long MAX_FILE_SIZE = 10*1024*1024; // 群聊最大人数 public static final long MAX_GROUP_MEMBER = 500; + // 在线状态过期时间 600s + public static final long ONLINE_TIMEOUT_SECOND = 600; } diff --git a/commom/src/main/java/com/bx/common/enums/FileTypeEnum.java b/commom/src/main/java/com/bx/common/enums/FileTypeEnum.java index 35091b1..a41ac1f 100644 --- a/commom/src/main/java/com/bx/common/enums/FileTypeEnum.java +++ b/commom/src/main/java/com/bx/common/enums/FileTypeEnum.java @@ -4,7 +4,9 @@ public enum FileTypeEnum { FILE(0,"文件"), IMAGE(1,"图片"), - VIDEO(2,"视频"); + VIDEO(2,"视频"), + AUDIO(3,"声音"); + private Integer code; diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java index 75deeda..3c62332 100644 --- a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java +++ b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java @@ -16,6 +16,7 @@ import com.bx.implatform.service.IGroupMessageService; import com.bx.implatform.service.IGroupService; import com.bx.implatform.session.SessionContext; import com.bx.implatform.vo.GroupMessageVO; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -24,7 +25,7 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; - +@Slf4j @Service public class GroupMessageServiceImpl extends ServiceImpl implements IGroupMessageService { @@ -86,6 +87,7 @@ public class GroupMessageServiceImpl extends ServiceImpl implements IPrivateMessageService { @@ -59,6 +60,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl { SendInfo sendInfo = new SendInfo(); sendInfo.setCmd(WSCmdEnum.HEART_BEAT.getCode()); ctx.channel().writeAndFlush(sendInfo); + + // 设置属性 + AttributeKey attr = AttributeKey.valueOf("HEARTBEAt_TIMES"); + Long heartbeatTimes = ctx.channel().attr(attr).get(); + ctx.channel().attr(attr).set(++heartbeatTimes); + if(heartbeatTimes%10 == 0){ + // 每心跳10次,用户在线状态续一次命 + attr = AttributeKey.valueOf("USER_ID"); + Long userId = ctx.channel().attr(attr).get(); + String key = RedisKey.IM_USER_SERVER_ID+userId; + redisTemplate.expire(key, Constant.ONLINE_TIMEOUT_SECOND, TimeUnit.SECONDS); + } } diff --git a/im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java b/im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java index a5225f8..64bd23a 100644 --- a/im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java +++ b/im-server/src/main/java/com/bx/imserver/websocket/processor/LoginProcessor.java @@ -1,6 +1,7 @@ package com.bx.imserver.websocket.processor; import cn.hutool.core.bean.BeanUtil; +import com.bx.common.contant.Constant; import com.bx.common.contant.RedisKey; import com.bx.common.enums.WSCmdEnum; import com.bx.common.model.im.LoginInfo; @@ -15,6 +16,7 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.HashMap; +import java.util.concurrent.TimeUnit; @Slf4j @Component @@ -39,12 +41,15 @@ public class LoginProcessor extends MessageProcessor { } // 绑定用户和channel WebsocketChannelCtxHolder.addChannelCtx(loginInfo.getUserId(),ctx); - // 设置属性 + // 设置用户id属性 AttributeKey attr = AttributeKey.valueOf("USER_ID"); ctx.channel().attr(attr).set(loginInfo.getUserId()); + // 心跳次数 + attr = AttributeKey.valueOf("HEARTBEAt_TIMES"); + ctx.channel().attr(attr).set(0L); // 在redis上记录每个user的channelId,15秒没有心跳,则自动过期 String key = RedisKey.IM_USER_SERVER_ID+loginInfo.getUserId(); - redisTemplate.opsForValue().set(key, WSServer.getServerId()); + redisTemplate.opsForValue().set(key, WSServer.getServerId(), Constant.ONLINE_TIMEOUT_SECOND, TimeUnit.SECONDS); // 响应ws SendInfo sendInfo = new SendInfo(); sendInfo.setCmd(WSCmdEnum.LOGIN.getCode()); diff --git a/im-ui/.env.production b/im-ui/.env.production index 49fc05a..acca7e2 100644 --- a/im-ui/.env.production +++ b/im-ui/.env.production @@ -1,6 +1,6 @@ ENV = 'production' # 接口地址 -VUE_APP_BASE_API = 'http://8.134.92.70/api' +VUE_APP_BASE_API = 'https://8.134.92.70:443/api' -VUE_APP_WS_URL = 'ws://8.134.92.70:81/im' \ No newline at end of file +VUE_APP_WS_URL = 'wss://8.134.92.70:81/im' \ No newline at end of file diff --git a/im-ui/package.json b/im-ui/package.json index 950f505..0413271 100644 --- a/im-ui/package.json +++ b/im-ui/package.json @@ -11,6 +11,7 @@ "axios": "^1.1.3", "core-js": "^3.6.5", "element-ui": "^2.15.10", + "js-audio-recorder": "^1.0.7", "sass": "^1.47.0", "sass-loader": "^7.3.1", "vue": "^2.6.11", @@ -50,7 +51,7 @@ "vue/no-unused-components": "off", "no-irregular-whitespace": "off", "no-debugger": "off", - "no-useless-escape": "off" + "no-useless-escape": "off" } }, "browserslist": [ diff --git a/im-ui/src/api/emotion.js b/im-ui/src/api/emotion.js index 3e571f2..fb4d0d1 100644 --- a/im-ui/src/api/emotion.js +++ b/im-ui/src/api/emotion.js @@ -2,7 +2,6 @@ const emoTextList = ['微笑', '撇嘴', '色', '发呆', '得意', '流泪', ' let transform = (content) => { - console.log(content) return content.replace(/\#[\u4E00-\u9FA5]{1,3}\;/gi, textToImg); } diff --git a/im-ui/src/components/chat/ChatBox.vue b/im-ui/src/components/chat/ChatBox.vue new file mode 100644 index 0000000..3ba8913 --- /dev/null +++ b/im-ui/src/components/chat/ChatBox.vue @@ -0,0 +1,494 @@ + + + + + diff --git a/im-ui/src/components/chat/ChatGroup.vue b/im-ui/src/components/chat/ChatGroup.vue deleted file mode 100644 index ae91911..0000000 --- a/im-ui/src/components/chat/ChatGroup.vue +++ /dev/null @@ -1,319 +0,0 @@ - - - - - diff --git a/im-ui/src/components/chat/ChatPrivate.vue b/im-ui/src/components/chat/ChatPrivate.vue deleted file mode 100644 index 8ece220..0000000 --- a/im-ui/src/components/chat/ChatPrivate.vue +++ /dev/null @@ -1,251 +0,0 @@ - - - - - diff --git a/im-ui/src/components/chat/ChatVoice.vue b/im-ui/src/components/chat/ChatVoice.vue new file mode 100644 index 0000000..cf3ff97 --- /dev/null +++ b/im-ui/src/components/chat/ChatVoice.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/im-ui/src/components/chat/MessageItem.vue b/im-ui/src/components/chat/MessageItem.vue index 089de0f..9e89f7c 100644 --- a/im-ui/src/components/chat/MessageItem.vue +++ b/im-ui/src/components/chat/MessageItem.vue @@ -14,7 +14,9 @@
- +
@@ -30,6 +32,9 @@ +
+ +
@@ -63,9 +68,29 @@ required: true } }, + data(){ + return { + audioPlayState: 'STOP', + } + + }, methods:{ handleSendFail(){ this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送") + }, + showFullImageBox(){ + let imageUrl = JSON.parse(this.msgInfo.content).originUrl; + if(imageUrl){ + this.$store.commit('showFullImageBox',imageUrl); + } + }, + handlePlayVoice(){ + if(!this.audio){ + this.audio = new Audio(); + } + this.audio.src = JSON.parse(this.msgInfo.content).url; + this.audio.play(); + this.handlePlayVoice = 'RUNNING'; } }, computed:{ @@ -160,6 +185,7 @@ flex-wrap: nowrap; flex-direction: row; align-items: center; + .send-image{ min-width: 300px; min-height: 200px; @@ -220,6 +246,11 @@ } } + + .im-msg-voice { + font-size: 14px; + cursor: pointer; + } } } diff --git a/im-ui/src/components/common/Emotion.vue b/im-ui/src/components/common/Emotion.vue index 53c3b6f..21e3307 100644 --- a/im-ui/src/components/common/Emotion.vue +++ b/im-ui/src/components/common/Emotion.vue @@ -1,11 +1,13 @@ @@ -37,6 +39,16 @@ } diff --git a/im-ui/src/view/Friend.vue b/im-ui/src/view/Friend.vue index 177f196..d3d6e79 100644 --- a/im-ui/src/view/Friend.vue +++ b/im-ui/src/view/Friend.vue @@ -13,7 +13,7 @@ -
+
@@ -122,7 +122,7 @@ data: friend }).then(() => { this.$store.commit("updateFriend", friend); - this.$store.commit("updateChatFromUser", user); + this.$store.commit("updateChatFromFriend", user); }) }, loadUserInfo(friend,index){ diff --git a/im-ui/src/view/Group.vue b/im-ui/src/view/Group.vue index f2202ca..ce691f0 100644 --- a/im-ui/src/view/Group.vue +++ b/im-ui/src/view/Group.vue @@ -11,7 +11,7 @@ @click="handleCreateGroup()">
-
+
@@ -22,7 +22,7 @@
{{activeGroup.remark}}({{groupMembers.length}})
-
+
@@ -74,7 +74,7 @@
-
+
@@ -306,7 +306,7 @@ .r-group-info { display: flex; - padding: 20px; + padding: 5px 20px; .r-group-form { flex: 1; @@ -351,7 +351,7 @@ } .r-group-member-list { - padding: 20px; + padding: 5px 20px; display: flex; align-items: center; flex-wrap: wrap; diff --git a/im-ui/src/view/Home.vue b/im-ui/src/view/Home.vue index f654c7d..85f6d84 100644 --- a/im-ui/src/view/Home.vue +++ b/im-ui/src/view/Home.vue @@ -23,7 +23,7 @@ - + @@ -34,7 +34,7 @@ - + { + this.setCookie('username',this.loginForm.username); + this.setCookie('password',this.loginForm.password); this.$message.success("登陆成功"); this.$router.push("/home/chat"); }) @@ -77,9 +79,37 @@ }, resetForm(formName) { this.$refs[formName].resetFields(); - } + }, + // 获取cookie、 + getCookie(name) { + let reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); + let arr = document.cookie.match(reg) + if (arr){ + return unescape(arr[2]); + } + return ''; + }, + // 设置cookie,增加到vue实例方便全局调用 + setCookie (name, value, expiredays) { + var exdate = new Date(); + exdate.setDate(exdate.getDate() + expiredays); + document.cookie = name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString()); + }, + // 删除cookie + delCookie (name) { + var exp = new Date(); + exp.setTime(exp.getTime() - 1); + var cval = this.getCookie(name); + if (cval != null){ + document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); + } + } + }, + mounted() { + this.loginForm.username = this.getCookie("username"); + // cookie存密码并不安全,暂时是为了方便 + this.loginForm.password = this.getCookie("password"); } - } diff --git a/im-ui/src/view/Register.vue b/im-ui/src/view/Register.vue index 00d942f..d1c4907 100644 --- a/im-ui/src/view/Register.vue +++ b/im-ui/src/view/Register.vue @@ -3,7 +3,7 @@
-
欢迎注册成为FLY CHAT用户
+
欢迎注册
@@ -142,6 +142,7 @@ font-size: 22px; font-weight: 600; letter-spacing: 2px; + text-align: center; text-transform: uppercase; }