From 0cde490c879d58007794ad3f3584c802f474889d Mon Sep 17 00:00:00 2001 From: xsx <825657193@qq.com> Date: Sun, 15 Oct 2023 03:03:49 +0800 Subject: [PATCH] =?UTF-8?q?uniapp=20=E5=8F=91=E9=80=81=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E3=80=81=E6=B6=88=E6=81=AF=E5=88=A0=E9=99=A4=E3=80=81=E6=92=A4?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/bx/implatform/enums/MessageType.java | 4 +- im-platform/src/main/resources/db/db.sql | 4 +- im-ui/public/favicon.ico | Bin 4286 -> 0 bytes im-ui/public/index.html | 2 +- im-ui/public/logo.png | Bin 0 -> 22672 bytes im-ui/src/api/enums.js | 4 +- im-ui/src/assets/logo.png | Bin 6849 -> 0 bytes im-ui/src/components/chat/ChatMessageItem.vue | 4 +- im-ui/src/store/chatStore.js | 7 +- im-uniapp/App.vue | 15 +- im-uniapp/common/enums.js | 4 +- im-uniapp/common/request.js | 28 +-- im-uniapp/common/wssocket.js | 19 +- .../chat-message-item/chat-message-item.vue | 182 ++++++++++------- .../components/file-upload/file-upload.vue | 94 +++++++++ .../components/image-upload/image-upload.vue | 15 +- im-uniapp/components/pop-menu/pop-menu.vue | 67 ++++++ im-uniapp/manifest.json | 5 +- im-uniapp/pages/chat/chat-box.vue | 191 ++++++++++++++---- im-uniapp/pages/login/login.vue | 4 +- im-uniapp/static/icon/iconfont.css | 14 +- im-uniapp/static/icon/iconfont.ttf | Bin 4672 -> 4972 bytes im-uniapp/static/logo.png | Bin 4023 -> 0 bytes im-uniapp/store/chatStore.js | 38 ++-- im-uniapp/store/groupStore.js | 4 +- im-uniapp/store/index.js | 18 +- im-uniapp/store/userStore.js | 5 +- 27 files changed, 537 insertions(+), 191 deletions(-) delete mode 100644 im-ui/public/favicon.ico create mode 100644 im-ui/public/logo.png delete mode 100644 im-ui/src/assets/logo.png create mode 100644 im-uniapp/components/file-upload/file-upload.vue create mode 100644 im-uniapp/components/pop-menu/pop-menu.vue delete mode 100644 im-uniapp/static/logo.png diff --git a/im-platform/src/main/java/com/bx/implatform/enums/MessageType.java b/im-platform/src/main/java/com/bx/implatform/enums/MessageType.java index 04f30f9..5e6d2e8 100644 --- a/im-platform/src/main/java/com/bx/implatform/enums/MessageType.java +++ b/im-platform/src/main/java/com/bx/implatform/enums/MessageType.java @@ -4,8 +4,8 @@ package com.bx.implatform.enums; public enum MessageType { TEXT(0,"文字"), - FILE(1,"文件"), - IMAGE(2,"图片"), + IMAGE(1,"图片"), + FILE(2,"文件"), AUDIO(3,"音频"), VIDEO(4,"视频"), RECALL(10,"撤回"), diff --git a/im-platform/src/main/resources/db/db.sql b/im-platform/src/main/resources/db/db.sql index 5e2365b..ba33925 100644 --- a/im-platform/src/main/resources/db/db.sql +++ b/im-platform/src/main/resources/db/db.sql @@ -45,8 +45,8 @@ create table `im_group`( `head_image_thumb` varchar(255) default '' comment '群头像缩略图', `notice` varchar(1024) default '' comment '群公告', `remark` varchar(255) default '' comment '群备注', - `deleted` tinyint(1) DEFAULT 0 comment '是否已删除', - `created_time` datetime DEFAULT CURRENT_TIMESTAMP comment '创建时间' + `deleted` tinyint(1) default 0 comment '是否已删除', + `created_time` datetime default CURRENT_TIMESTAMP comment '创建时间' )ENGINE=InnoDB CHARSET=utf8mb3 comment '群'; create table `im_group_member`( diff --git a/im-ui/public/favicon.ico b/im-ui/public/favicon.ico deleted file mode 100644 index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S diff --git a/im-ui/public/index.html b/im-ui/public/index.html index 5ae1079..724a362 100644 --- a/im-ui/public/index.html +++ b/im-ui/public/index.html @@ -4,7 +4,7 @@ - + 盒子IM diff --git a/im-ui/public/logo.png b/im-ui/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d5690e32d21897e1e093104ba7d3b50695591a45 GIT binary patch literal 22672 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 literal 0 HcmV?d00001 diff --git a/im-ui/src/api/enums.js b/im-ui/src/api/enums.js index e58857d..eb41941 100644 --- a/im-ui/src/api/enums.js +++ b/im-ui/src/api/enums.js @@ -1,8 +1,8 @@ const MESSAGE_TYPE = { TEXT: 0, - FILE:1, - IMAGE:2, + IMAGE:1, + FILE:2, AUDIO:3, VIDEO:4, RECALL:10, diff --git a/im-ui/src/assets/logo.png b/im-ui/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b5053b0837ebea6e87a2d339a43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6849 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
-
+
-
+
{{data.name}} diff --git a/im-ui/src/store/chatStore.js b/im-ui/src/store/chatStore.js index ed86801..c11ed1a 100644 --- a/im-ui/src/store/chatStore.js +++ b/im-ui/src/store/chatStore.js @@ -1,3 +1,4 @@ +import {MESSAGE_TYPE} from "../api/enums.js" export default { state: { @@ -85,11 +86,11 @@ export default { } } // 插入新的数据 - if(msgInfo.type == 1){ + if(msgInfo.type == MESSAGE_TYPE.IMAGE ){ chat.lastContent = "[图片]"; - }else if(msgInfo.type == 2){ + }else if(msgInfo.type == MESSAGE_TYPE.FILE){ chat.lastContent = "[文件]"; - }else if(msgInfo.type == 3){ + }else if(msgInfo.type == MESSAGE_TYPE.AUDIO){ chat.lastContent = "[语音]"; }else{ chat.lastContent = msgInfo.content; diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue index 3c216ef..4463d59 100644 --- a/im-uniapp/App.vue +++ b/im-uniapp/App.vue @@ -11,16 +11,18 @@ } }, methods: { - init(loginInfo) { + init() { // 加载数据 store.dispatch("load").then(() => { // 初始化websocket - this.initWebSocket(loginInfo); + this.initWebSocket(); }).catch((e) => { + console.log(e); this.exit(); }) }, - initWebSocket(loginInfo) { + initWebSocket() { + let loginInfo = uni.getStorageSync("loginInfo") let userId = store.state.userStore.userInfo.id; wsApi.createWebSocket(process.env.WS_URL, loginInfo.accessToken); wsApi.onopen(() => { @@ -129,7 +131,7 @@ console.log("exit"); wsApi.closeWebSocket(); uni.removeStorageSync("loginInfo"); - uni.navigateTo({ + uni.reLaunch({ url: "/pages/login/login" }) }, @@ -142,10 +144,9 @@ }, onLaunch() { // 登录状态校验 - let loginInfo = uni.getStorageSync("loginInfo"); - if (loginInfo) { + if (uni.getStorageSync("loginInfo")) { // 初始化 - this.init(loginInfo) + this.init() } else { // 跳转到登录页 uni.navigateTo({ diff --git a/im-uniapp/common/enums.js b/im-uniapp/common/enums.js index e58857d..a902aee 100644 --- a/im-uniapp/common/enums.js +++ b/im-uniapp/common/enums.js @@ -1,8 +1,8 @@ const MESSAGE_TYPE = { TEXT: 0, - FILE:1, - IMAGE:2, + IMAGE: 1, + FILE:2, AUDIO:3, VIDEO:4, RECALL:10, diff --git a/im-uniapp/common/request.js b/im-uniapp/common/request.js index c70648a..f0ca4d7 100644 --- a/im-uniapp/common/request.js +++ b/im-uniapp/common/request.js @@ -24,28 +24,30 @@ const request = (options) => { console.log("token失效,尝试重新获取") if (isRefreshToken) { // 正在刷新token,把其他请求存起来 - return new Promise(resolve => { - requestList.push(() => { - resolve(request(options)) - }) + requestList.push(() => { + resolve(request(options)) }) + return; } isRefreshToken = true; // 发送请求, 进行刷新token操作, 获取新的token - const res = await reqRefreshToken(loginInfo).catch((res) => { - return navToLogin(); - }).finally(()=>{ - requestList.forEach(cb => cb()); + const res = await reqRefreshToken(loginInfo); + if (!res || res.data.code != 200) { requestList = []; isRefreshToken = false; - }) - if (res.data.code != 200) { - return navToLogin(); + console.log("刷新token失败") + navToLogin(); + return; } - // 保存token uni.setStorageSync("loginInfo", res.data.data); + requestList.forEach(cb => cb()); + requestList = []; + isRefreshToken = false; + // 保存token + console.log(res.data.data.accessToken) + // 重新发送刚才的请求 - return request(options) + return resolve(request(options)) } else { uni.showToast({ diff --git a/im-uniapp/common/wssocket.js b/im-uniapp/common/wssocket.js index 6da3e33..22e6fda 100644 --- a/im-uniapp/common/wssocket.js +++ b/im-uniapp/common/wssocket.js @@ -4,7 +4,7 @@ let messageCallBack = null; let openCallBack = null; let isConnect = false; //连接标识 避免重复连接 let hasLogin = false; - +let hasInit = false; let createWebSocket = (url, token) => { wsurl = url; accessToken = token; @@ -27,7 +27,12 @@ let initWebSocket = () => { reConnect(); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接 } }); - + + // 不能绑定多次事件,不然多触发,即便之前已经调了uni.closeSocket + if(hasInit){ + return; + } + hasInit = true; uni.onSocketOpen((res) => { console.log("WebSocket连接已打开"); isConnect = true; @@ -77,7 +82,7 @@ let initWebSocket = () => { showCancel: false, }) }) - + }; //定义重连函数 @@ -97,15 +102,19 @@ let closeWebSocket = () => { resolve(); return; } - console.log("关闭websocket连接"); uni.closeSocket({ - code: 1000, + code: 3000, complete: (res) => { + console.log("关闭websocket连接"); hasLogin = false; isConnect = false; resolve(); + }, + fail:(e)=>{ + console.log("关闭websocket连接失败",e); } }) + }) diff --git a/im-uniapp/components/chat-message-item/chat-message-item.vue b/im-uniapp/components/chat-message-item/chat-message-item.vue index a5a3e2e..313ca3a 100644 --- a/im-uniapp/components/chat-message-item/chat-message-item.vue +++ b/im-uniapp/components/chat-message-item/chat-message-item.vue @@ -1,49 +1,58 @@ @@ -62,36 +71,52 @@ msgInfo: { type: Object, required: true - }, - menu:{ - type: Boolean, - default: true } }, data() { return { audioPlayState: 'STOP', - rightMenu: { + menu: { show: false, - pos: { - x: 0, - y: 0 - } + style: "" } } }, methods: { - handleSendFail() { - this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送") + onShowMenu(e) { + uni.getSystemInfo({ + success: (res) => { + let touches = e.touches[0]; + let style = ""; + /* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */ + if (touches.clientY > (res.windowHeight / 2)) { + style = `bottom:${res.windowHeight-touches.clientY}px;`; + } else { + style = `top:${touches.clientY}px;`; + } + if (touches.clientX > (res.windowWidth / 2)) { + style += `right:${res.windowWidth-touches.clientX}px;`; + } else { + style += `left:${touches.clientX}px;`; + } + this.menu.style = style; + // + this.$nextTick(() => { + this.menu.show = true; + }); + } + }) + + }, - showFullImageBox() { - let imageUrl = JSON.parse(this.msgInfo.content).originUrl; - if (imageUrl) { - this.$store.commit('showFullImageBox', imageUrl); - } + onSendFail() { + uni.showToast({ + title: "该文件已发送失败,目前不支持自动重新发送,建议手动重新发送", + icon: "none" + }) }, - handlePlayVoice() { + onPlayVoice() { if (!this.audio) { this.audio = new Audio(); } @@ -99,27 +124,33 @@ this.audio.play(); this.handlePlayVoice = 'RUNNING'; }, - showRightMenu(e) { - this.rightMenu.pos = { - x: e.x, - y: e.y - }; - this.rightMenu.show = "true"; - }, - handleSelectMenu(item) { + onSelectMenu(item) { this.$emit(item.key.toLowerCase(), this.msgInfo); + this.menu.show = false; + }, + onShowFullImage() { + let imageUrl = JSON.parse(this.msgInfo.content).originUrl; + uni.previewImage({ + urls: [imageUrl] + }) + }, + onShowUserInfo(userId){ + uni.navigateTo({ + url: "/pages/common/user-info?id=" + userId + }) } + }, computed: { loading() { return !this.isTimeout && this.msgInfo.loadStatus && this.msgInfo.loadStatus === "loading"; }, loadFail() { - return this.msgInfo.loadStatus && (this.isTimeout || this.msgInfo.loadStatus === "fail"); + return this.msgInfo.loadStatus && (this.isTimeout || this.msgInfo.loadStatus === "fail"); }, - isTimeout(){ - return (new Date().getTime() - new Date(this.msgInfo.sendTime).getTime()) > 30*1000; - + isTimeout() { + return (new Date().getTime() - new Date(this.msgInfo.sendTime).getTime()) > 30 * 1000; + }, data() { return JSON.parse(this.msgInfo.content) @@ -139,29 +170,36 @@ items.push({ key: 'DELETE', name: '删除', - icon: 'el-icon-delete' + icon: 'trash' }); if (this.msgInfo.selfSend && this.msgInfo.id > 0) { items.push({ key: 'RECALL', name: '撤回', - icon: 'el-icon-refresh-left' + icon: 'refreshempty' + }); + } + if (this.msgInfo.type == this.$enums.MESSAGE_TYPE.FILE) { + items.push({ + key: 'DOWNLOAD', + name: '下载并打开', + icon: 'download' }); } return items; } - }, - mounted() { - //console.log(this.msgInfo); } + } - + \ No newline at end of file diff --git a/im-uniapp/components/file-upload/file-upload.vue b/im-uniapp/components/file-upload/file-upload.vue new file mode 100644 index 0000000..a2b54ac --- /dev/null +++ b/im-uniapp/components/file-upload/file-upload.vue @@ -0,0 +1,94 @@ + + + + + \ No newline at end of file diff --git a/im-uniapp/components/image-upload/image-upload.vue b/im-uniapp/components/image-upload/image-upload.vue index 75b970f..30723ec 100644 --- a/im-uniapp/components/image-upload/image-upload.vue +++ b/im-uniapp/components/image-upload/image-upload.vue @@ -17,7 +17,11 @@ props: { maxSize: { type: Number, - default: null + default: 5*1024*1024 + }, + sourceType:{ + type: String, + default: 'album' }, onBefore: { type: Function, @@ -34,14 +38,12 @@ }, methods: { selectAndUpload() { - console.log("selectAndUpload"); uni.chooseImage({ count: 9, //最多可以选择的图片张数,默认9 - sourceType: ['album'], //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项 + sourceType: [this.sourceType], //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项 sizeType: ['original'], //original 原图,compressed 压缩图,默认二者都有 success: (res) => { res.tempFiles.forEach((file) => { - console.log("选择文件"); // 校验大小 if (this.maxSize && file.size > this.maxSize) { this.$message.error(`文件大小不能超过 ${this.fileSizeStr}!`); @@ -58,7 +60,6 @@ }) }, uploadImage(file) { - console.log("上传文件") uni.uploadFile({ url: process.env.BASE_URL + '/image/upload', header: { @@ -71,13 +72,11 @@ if(data.code != 200){ this.onError && this.onError(file, data); }else{ - console.log("上传成功") this.onSuccess && this.onSuccess(file, data); } }, fail: (err) => { - console.log("上传失败") - console.log(this.onError) + console.log(err); this.onError && this.onError(file, err); } }) diff --git a/im-uniapp/components/pop-menu/pop-menu.vue b/im-uniapp/components/pop-menu/pop-menu.vue new file mode 100644 index 0000000..065890a --- /dev/null +++ b/im-uniapp/components/pop-menu/pop-menu.vue @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/im-uniapp/manifest.json b/im-uniapp/manifest.json index e90c7d3..bd24642 100644 --- a/im-uniapp/manifest.json +++ b/im-uniapp/manifest.json @@ -68,5 +68,8 @@ "uniStatistics" : { "enable" : false }, - "vueVersion" : "3" + "vueVersion" : "3", + "h5" : { + "title" : "盒子IM" + } } diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue index 4850439..ca29d9b 100644 --- a/im-uniapp/pages/chat/chat-box.vue +++ b/im-uniapp/pages/chat/chat-box.vue @@ -2,12 +2,13 @@ {{title}} - + @@ -17,13 +18,11 @@ + :adjust-position="false" @confirm="sendTextMessage()" @keyboardheightchange="onKeyboardheightchange" + confirm-type="send" confirm-hold :hold-keyboard="true"> - - + + @@ -32,16 +31,36 @@ - 相册 - - - {{ tool.name }} + + + + + 拍摄 + + + + + + 文件 + + + + 语音输入 + + + + 呼叫 + + @@ -69,24 +88,7 @@ scrollMsgIdx: 0, // 滚动条定位为到哪条消息 chatTabBox: 'none', showKeyBoard: false, - keyboardHeight: 322, - tools: [{ - name: "拍摄", - icon: "icon-camera" - }, - { - name: "语音输入", - icon: "icon-microphone" - }, - { - name: "文件", - icon: "icon-folder" - }, - { - name: "呼叫", - icon: "icon-call" - } - ] + keyboardHeight: 322 } }, methods: { @@ -151,7 +153,7 @@ } }, scrollToMsgIdx(idx) { - // 踩坑:如果scrollMsgIdx值没变化,滚动条不会移动 + // 如果scrollMsgIdx值没变化,滚动条不会移动 if (idx == this.scrollMsgIdx && idx > 0) { this.$nextTick(() => { // 先滚动到上一条 @@ -168,7 +170,6 @@ }, switchChatTabBox(chatTabBox, hideKeyBoard) { this.chatTabBox = chatTabBox; - this.scrollToBottom(); if (hideKeyBoard) { uni.hideKeyboard(); } @@ -176,7 +177,8 @@ selectEmoji(emoText) { this.sendText += `#${emoText};`; }, - onKeyboardheightchange(e) {; + onKeyboardheightchange(e) { + ; if (e.detail.height > 0) { this.showKeyBoard = true; this.switchChatTabBox('none', false) @@ -185,9 +187,6 @@ this.showKeyBoard = false; } }, - onSendTextBlur() { - //this.switchChatTabBox("none") - }, onUploadImageBefore(file) { let data = { originUrl: file.path, @@ -200,7 +199,7 @@ content: JSON.stringify(data), sendTime: new Date().getTime(), selfSend: true, - type: 1, + type: this.$enums.MESSAGE_TYPE.IMAGE, loadStatus: "loading" } // 填充对方id @@ -231,13 +230,121 @@ msgInfo.loadStatus = 'fail'; this.$store.commit("insertMessage", msgInfo); }, - onClickTool(tool) { - switch (tool.name) { - case "相册": - break; - + onUploadFileBefore(file) { + let data = { + name: file.name, + size: file.size, + url: file.path + } + let msgInfo = { + id: 0, + sendId: this.mine.id, + content: JSON.stringify(data), + sendTime: new Date().getTime(), + selfSend: true, + type: this.$enums.MESSAGE_TYPE.FILE, + loadStatus: "loading" + } + // 填充对方id + this.fillTargetId(msgInfo, this.chat.targetId); + // 插入消息 + this.$store.commit("insertMessage", msgInfo); + // 借助file对象保存 + file.msgInfo = msgInfo; + // 滚到最低部 + this.scrollToBottom(); + return true; + }, + onUploadFileSuccess(file, res) { + let data = { + name: file.name, + size: file.size, + url: res.data + } + let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); + msgInfo.content = JSON.stringify(data); + this.$http({ + url: this.messageAction, + method: 'POST', + data: msgInfo + }).then((id) => { + msgInfo.loadStatus = 'ok'; + msgInfo.id = id; + this.$store.commit("insertMessage", msgInfo); + }) + }, + onUploadFileFail(file, res) { + let msgInfo = JSON.parse(JSON.stringify(file.msgInfo)); + msgInfo.loadStatus = 'fail'; + this.$store.commit("insertMessage", msgInfo); + }, + onDeleteMessage(msgInfo) { + uni.showModal({ + title: '删除消息', + content: '确认删除消息?', + success: (res) => { + if (!res.cancel) { + this.$store.commit("deleteMessage", msgInfo); + uni.showToast({ + title: "删除成功", + icon: "none" + }) + } + } + }) + }, + onRecallMessage(msgInfo) { + uni.showModal({ + title: '撤回消息', + content: '确认撤回消息?', + success: (res) => { + if (!res.cancel) { + let url = `/message/${this.chat.type.toLowerCase()}/recall/${msgInfo.id}` + this.$http({ + url: url, + method: 'DELETE' + }).then(() => { + msgInfo = JSON.parse(JSON.stringify(msgInfo)); + msgInfo.type = this.$enums.MESSAGE_TYPE.RECALL; + msgInfo.content = '你撤回了一条消息'; + this.$store.commit("insertMessage", msgInfo); + }) + } + } + }) + }, + onDownloadFile(msgInfo) { + let url = JSON.parse(msgInfo.content).url; + uni.downloadFile({ + url: url, + success(res) { + if (res.statusCode === 200) { + var filePath = encodeURI(res.tempFilePath); + uni.openDocument({ + filePath: filePath, + showMenu: true + }); + } + }, + fail(e){ + console.log(e); + uni.showToast({ + title: "文件下载失败", + icon: "none" + }) + } + }); + }, + onShowMore(){ + if (this.chat.type == "GROUP") { + uni.navigateTo({ + url: "/pages/group/group-info?id="+this.group.id + }) + }else{ + uni.navigateTo({ + url: "/pages/common/user-info?id="+this.friend.id + }) } - }, loadGroup(groupId) { this.$http({ diff --git a/im-uniapp/pages/login/login.vue b/im-uniapp/pages/login/login.vue index ad8c3cc..65c535b 100644 --- a/im-uniapp/pages/login/login.vue +++ b/im-uniapp/pages/login/login.vue @@ -49,8 +49,8 @@ console.log("登录成功,自动跳转到聊天页面...") uni.setStorageSync("loginInfo", data); // 调用App.vue的初始化方法 - getApp().init(data) - // 跳转到聊天页面 + getApp().init() + // 跳转到聊天页面 uni.switchTab({ url: "/pages/chat/chat" }) diff --git a/im-uniapp/static/icon/iconfont.css b/im-uniapp/static/icon/iconfont.css index 1c4976b..e2eb2a9 100644 --- a/im-uniapp/static/icon/iconfont.css +++ b/im-uniapp/static/icon/iconfont.css @@ -1,6 +1,6 @@ @font-face { font-family: "iconfont"; /* Project id 4272106 */ - src: url('iconfont.ttf?t=1696173135884') format('truetype'); + src: url('iconfont.ttf?t=1697301725830') format('truetype'); } .iconfont { @@ -11,6 +11,14 @@ -moz-osx-font-smoothing: grayscale; } +.icon-file:before { + content: "\e671"; +} + +.icon-add:before { + content: "\e66c"; +} + .icon-warning-circle-fill:before { content: "\e848"; } @@ -19,10 +27,6 @@ content: "\e93d"; } -.icon-add-circle:before { - content: "\e664"; -} - .icon-camera:before { content: "\e600"; } diff --git a/im-uniapp/static/icon/iconfont.ttf b/im-uniapp/static/icon/iconfont.ttf index 2b19ac5df4342aeca11c8eceaa75480d1231a3b7..0eed9cc4962ebadbe89636ad089808e233e55634 100644 GIT binary patch delta 1113 zcmaJ-OGs2v82-<>=blMte2jBvY&1t_)H|uS*UWfF7_De!^gysAlCUXX+4zVQbP+dN zv`HbE+DHqbO;|)Afq{^;h!U6SB3k6;py0xd?VRa9a}_M8bMN<`|8c(W{O4b)+0vh$ zv_70St^v>*#CTt7qL-zPUIAc>0M2LqJ<0Cc#p53V;3vZD$Asg%@*I7vLrwqS=y;PO zy8}SBFm6f>-%e_??#IY~fpK6kIX*(F;WO3`V_Y?q9PBB6+58TmxDD^?8yUWzH~J|( zKL${;Fuf2yQwRjlAtrD6Q(Z;PJK$uP09bDuyRpA#e`Oyqt~|l`5Kx)LC3%JE0NGCG z)4JqJE(W|=$$19u`FLmr7|h_wBT$SPmjF>L{30P*MY~9edtyRZVs@i-vn87a_+K@> zPRkPnb^i4MsE~*KIiLVs*d@XHoxt%{d=TOD>y#1;D{{TbS-_KcrwwFdZ#GZ|gx>}# zf=JjvZ4j+Ca@=bDdp6`G#Donw4PjZ*Ai;_ItPN}tHc(Uon}y958?tR& zk6@daWR!fPKnE1AykalZCiS7Zj5TCtmzA4JBa}cDm~aj*!*zUYSg#K1-0RkS(O|@E zbjNfD4>ypIZncnDIO_9yf*~E#W;Dnvh~`U>NZhUQa4^JeN=!fK*G3~|Oh-Oel?#jB zs?2nyVN}xkO2cIm#^zK`33xLazuO;Br1)@8;Dn$ zklsS7rHPpd(ugynU=0nNK701`z))u2v4*-j&3N4G?E10qTx9AbQ&l#pvJ;9rCEY1i zQLY~3o!V3QgP2oT{hN3qCkOMhERW1j@R*Ynrr)~DT%-tC@10bSlI-qIe{~;8Z@b%m E13v8Ww*UYD delta 744 zcmZvYO=uHQ6ot>5nNG}~jmcPST1!ZiNOzQTW{42*4d1+b@4R#Fop&(wDzSdH zzVv=?0#IV4G&8$ejlKQw1kg4BU!ztjn#qSRHUWGjxf%C>M`rLa(WBFz=r$t}Kc;-thYg=CS$WTqU$w*aEr}>^HNxaMQc=YogBpj;-B& zc4{;T!E@x!rTW0N?!qDb8VkUu(Zaj--ul_PrRi#u`4K2~mCM!ztpV}f3Mti4I%R`w1ymav7O|k3)?}OE^G|B>cSBq z+0}-_T!7qQLO2(`(8$KVg|8zn|L$xI4IGFoVnuvbZmTiP(6+SST^F|>>0S|Lht{t8 zRL#M_FfP-^bijL2Ex86}T7a_xp;b Qd8T~*MtQbk^+&G$1@Zx+3;+NC diff --git a/im-uniapp/static/logo.png b/im-uniapp/static/logo.png deleted file mode 100644 index b5771e209bb677e2ebd5ff766ad5ee11790f305a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4023 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 SYs}WS&%*SCNx89m_ { + let userId = userStore.state.userInfo.id; uni.getStorage({ - key:"chats", + key:"chats-"+userId, success(res) { context.commit("setChats",res.data); resolve() diff --git a/im-uniapp/store/groupStore.js b/im-uniapp/store/groupStore.js index bd87b57..1920270 100644 --- a/im-uniapp/store/groupStore.js +++ b/im-uniapp/store/groupStore.js @@ -44,8 +44,8 @@ export default { }).then((groups) => { context.commit("setGroups", groups); resolve(); - }).catch(() => { - reject(); + }).catch((res) => { + reject(res); }) }); } diff --git a/im-uniapp/store/index.js b/im-uniapp/store/index.js index 7496fc6..83cf159 100644 --- a/im-uniapp/store/index.js +++ b/im-uniapp/store/index.js @@ -2,7 +2,9 @@ import chatStore from './chatStore.js'; import friendStore from './friendStore.js'; import userStore from './userStore.js'; import groupStore from './groupStore.js'; -import {createStore} from 'vuex'; +import { + createStore +} from 'vuex'; const store = createStore({ modules: { chatStore, @@ -13,12 +15,14 @@ const store = createStore({ state: {}, actions: { load(context) { - const promises = []; - promises.push(this.dispatch("loadUser")); - promises.push(this.dispatch("loadFriend")); - promises.push(this.dispatch("loadGroup")); - promises.push(this.dispatch("loadChat")); - return Promise.all(promises); + return this.dispatch("loadUser").then(() => { + const promises = []; + promises.push(this.dispatch("loadFriend")); + promises.push(this.dispatch("loadGroup")); + promises.push(this.dispatch("loadChat")); + return Promise.all(promises); + }) + } }, strict: true diff --git a/im-uniapp/store/userStore.js b/im-uniapp/store/userStore.js index 5c3971f..2626691 100644 --- a/im-uniapp/store/userStore.js +++ b/im-uniapp/store/userStore.js @@ -24,10 +24,11 @@ export default { url: '/user/self', method: 'GET' }).then((userInfo) => { + console.log(userInfo) context.commit("setUserInfo",userInfo); resolve(); - }).catch(()=>{ - reject(); + }).catch((res)=>{ + reject(res); }); }) }