diff --git a/im-ui/src/store/chatStore.js b/im-ui/src/store/chatStore.js
index 4bc504e..505cc70 100644
--- a/im-ui/src/store/chatStore.js
+++ b/im-ui/src/store/chatStore.js
@@ -174,8 +174,16 @@ export default {
});
chat.lastTimeTip = msgInfo.sendTime;
}
- // 新的消息
- chat.messages.push(msgInfo);
+ // 根据id顺序插入,防止消息乱序
+ let insertPos = chat.messages.length;
+ for (let idx in chat.messages) {
+ if (chat.messages[idx].id && msgInfo.id < chat.messages[idx].id) {
+ insertPos = idx;
+ console.log(`消息出现乱序,位置:${chat.messages.length},修正至:${insertPos}`);
+ break;
+ }
+ }
+ chat.messages.splice(insertPos, 0, msgInfo);
this.commit("saveToStorage");
},
updateMessage(state, msgInfo) {
diff --git a/im-ui/src/view/Home.vue b/im-ui/src/view/Home.vue
index d23677b..6ad830a 100644
--- a/im-ui/src/view/Home.vue
+++ b/im-ui/src/view/Home.vue
@@ -29,7 +29,7 @@
@@ -372,10 +372,12 @@
width: 60px;
bottom: 40px;
color: #aaaaaa;
- font-size: 24px;
text-align: center;
cursor: pointer;
+ .icon {
+ font-size: 28px;
+ }
&:hover {
color: white !important;
}
diff --git a/im-ui/src/view/Login.vue b/im-ui/src/view/Login.vue
index f4031ec..f3d8b2f 100644
--- a/im-ui/src/view/Login.vue
+++ b/im-ui/src/view/Login.vue
@@ -5,35 +5,31 @@
盒子IM 2.0版本已上线:
- - 加入uniapp移动版本,支持移动端和web端同时在线,多端消息同步
- - 目前移动端仅兼容h5和微信小程序,后续会继续兼容更多终端类型
+ - 加入uniapp移动端,支持移动端和web端同时在线,多端消息同步
+ - 目前uniapp移动端支持安卓、ios、h5、微信小程序
- 聊天窗口支持粘贴截图、@群成员、已读未读显示
- - 页面风格升级:表情包更新、自动生成文字头像等
- 支持群聊已读显示(回执消息)
- 语雀文档
盒子IM详细介绍文档,目前限时免费开放中
-
-
最近更新(2024-02-24):
-
- - uniapp端兼容ios和andriod,
- 点击下载安卓客户端
-
- - uniapp端的启动和打包方式有所变化,具体请参考语雀文档
-
-
+
如果本项目对您有帮助,请在gitee上帮忙点个star
diff --git a/im-uniapp/App.vue b/im-uniapp/App.vue
index 49665dd..5a3a7fe 100644
--- a/im-uniapp/App.vue
+++ b/im-uniapp/App.vue
@@ -106,6 +106,10 @@
// webrtc 信令
if (msg.type >= enums.MESSAGE_TYPE.RTC_CALL_VOICE &&
msg.type <= enums.MESSAGE_TYPE.RTC_CANDIDATE) {
+ // #ifdef MP-WEIXIN
+ // 小程序不支持音视频
+ return;
+ // #endif
// 被呼叫,弹出视频页面
if(msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE
|| msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO){
diff --git a/im-uniapp/common/recorder-app.js b/im-uniapp/common/recorder-app.js
new file mode 100644
index 0000000..dce0cbf
--- /dev/null
+++ b/im-uniapp/common/recorder-app.js
@@ -0,0 +1,62 @@
+import UNI_APP from '@/.env.js';
+
+const rc = uni.getRecorderManager();
+// 录音开始时间
+let startTime = null;
+
+let start = () => {
+ return new Promise((resolve, reject) => {
+ rc.onStart(() => {
+ startTime = new Date();
+ resolve()
+ });
+ rc.onError((e) => {
+ console.log(e);
+ reject(e)
+ })
+ rc.start({
+ format: 'mp3' // 录音格式,可选值:aac/mp3
+ });
+ })
+}
+
+let pause = () => {
+ rc.stop();
+}
+
+let close = () => {
+ rc.stop();
+}
+
+let upload = () => {
+ return new Promise((resolve, reject) => {
+ rc.onStop((wavFile, a, b) => {
+ uni.uploadFile({
+ url: UNI_APP.BASE_URL + '/file/upload',
+ header: {
+ accessToken: uni.getStorageSync("loginInfo").accessToken
+ },
+ filePath: wavFile.tempFilePath,
+ name: 'file',
+ success: (res) => {
+ const duration = (new Date().getTime() - startTime.getTime()) / 1000
+ const data = {
+ duration: Math.round(duration),
+ url: JSON.parse(res.data).data
+ }
+ resolve(data);
+ },
+ fail: (e) => {
+ reject(e);
+ }
+ })
+ });
+ })
+}
+
+export {
+ start,
+ pause,
+ close,
+ upload
+}
\ No newline at end of file
diff --git a/im-uniapp/common/recorder-h5.js b/im-uniapp/common/recorder-h5.js
new file mode 100644
index 0000000..1f435ca
--- /dev/null
+++ b/im-uniapp/common/recorder-h5.js
@@ -0,0 +1,54 @@
+import Recorder from 'js-audio-recorder';
+import UNI_APP from '@/.env.js';
+
+let rc = null;
+let start = () => {
+ if(rc != null){
+ close();
+ }
+ rc = new Recorder();
+ return rc.start();
+}
+
+let pause = () => {
+ rc.pause();
+}
+
+let close = () => {
+ rc.destroy();
+ rc = null;
+}
+
+let upload = () => {
+ return new Promise((resolve, reject) => {
+ const wavBlob = rc.getWAVBlob();
+ const newbolb = new Blob([wavBlob], { type: 'audio/wav'})
+ const name = new Date().getDate() + '.wav';
+ const file = new File([newbolb], name)
+ uni.uploadFile({
+ url: UNI_APP.BASE_URL + '/file/upload',
+ header: {
+ accessToken: uni.getStorageSync("loginInfo").accessToken
+ },
+ file: file,
+ name: 'file',
+ success: (res) => {
+ const data = {
+ duration: parseInt(rc.duration),
+ url: JSON.parse(res.data).data
+ }
+ resolve(data);
+ },
+ fail: (e) => {
+ reject(e);
+ }
+ })
+ })
+}
+
+export {
+ start,
+ pause,
+ close,
+ upload
+}
\ No newline at end of file
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 74be926..43dc856 100644
--- a/im-uniapp/components/chat-message-item/chat-message-item.vue
+++ b/im-uniapp/components/chat-message-item/chat-message-item.vue
@@ -1,13 +1,16 @@
- {{msgInfo.content}}
+
+ {{msgInfo.content}}
{{$date.toTimeText(msgInfo.sendTime)}}
-
+
{{showName}}
@@ -26,7 +29,6 @@
-
@@ -40,31 +42,28 @@
-
-
-
+
+
+ {{JSON.parse(msgInfo.content).duration+'"'}}
+
+
+
+
+
+
{{msgInfo.content}}
-
已读
未读
-
{{msgInfo.readedCount}}人已读
-
@@ -97,6 +96,7 @@
data() {
return {
audioPlayState: 'STOP',
+ innerAudioContext: null,
menu: {
show: false,
style: ""
@@ -135,13 +135,31 @@
icon: "none"
})
},
- onPlayVoice() {
- if (!this.audio) {
- this.audio = new Audio();
+ onPlayAudio() {
+ // 初始化音频播放器
+ if (!this.innerAudioContext) {
+ this.innerAudioContext = uni.createInnerAudioContext();
+ let url = JSON.parse(this.msgInfo.content).url;
+ this.innerAudioContext.src = url;
+ this.innerAudioContext.onEnded((e) => {
+ console.log('停止')
+ this.audioPlayState = "STOP"
+ })
+ this.innerAudioContext.onError((e) =>{
+ console.log("播放音频出错");
+ console.log(e)
+ });
+ }
+ if (this.audioPlayState == 'STOP') {
+ this.innerAudioContext.play();
+ this.audioPlayState = "PLAYING";
+ } else if (this.audioPlayState == 'PLAYING') {
+ this.innerAudioContext.pause();
+ this.audioPlayState = "PAUSE"
+ } else if (this.audioPlayState == 'PAUSE') {
+ this.innerAudioContext.play();
+ this.audioPlayState = "PLAYING"
}
- this.audio.src = JSON.parse(this.msgInfo.content).url;
- this.audio.play();
- this.handlePlayVoice = 'RUNNING';
},
onSelectMenu(item) {
this.$emit(item.key.toLowerCase(), this.msgInfo);
@@ -357,12 +375,24 @@
}
+ .chat-msg-audio {
+ display: flex;
+ align-items: center;
-
+ .chat-audio-text {
+ padding-right: 8px;
+ }
+
+ .icon-voice-play {
+ font-size: 20px;
+ padding-right: 8px;
+ }
+ }
.chat-realtime {
display: flex;
align-items: center;
+
.iconfont {
font-size: 20px;
padding-right: 8px;
@@ -373,13 +403,13 @@
display: block;
.chat-readed {
- font-size: 10px;
- color: #ccc;
+ font-size: 12px;
+ color: #888;
font-weight: 600;
}
-
+
.chat-unread {
- font-size: 10px;
+ font-size: 12px;
color: #f23c0f;
font-weight: 600;
}
@@ -436,14 +466,28 @@
.chat-msg-file {
flex-direction: row-reverse;
}
-
+
+ .chat-msg-audio {
+ flex-direction: row-reverse;
+
+ .chat-audio-text {
+ padding-right: 0;
+ padding-left: 8px;
+ }
+ .icon-voice-play {
+ transform: rotateY(180deg);
+ }
+ }
+
.chat-realtime {
display: flex;
flex-direction: row-reverse;
+
.iconfont {
transform: rotateY(180deg);
}
}
+
}
}
}
diff --git a/im-uniapp/components/chat-record/chat-record.vue b/im-uniapp/components/chat-record/chat-record.vue
new file mode 100644
index 0000000..623333a
--- /dev/null
+++ b/im-uniapp/components/chat-record/chat-record.vue
@@ -0,0 +1,227 @@
+
+
+ {{recording?'正在录音':'长按 说话'}}
+
+
+
+
+
+
+
+
+
+
+ {{recordTip}}
+
+
+
+ {{moveToCancel? '松手取消':'松手发送,上划取消'}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/im-uniapp/main.js b/im-uniapp/main.js
index 62747fa..f3f3774 100644
--- a/im-uniapp/main.js
+++ b/im-uniapp/main.js
@@ -6,6 +6,13 @@ import * as date from './common/date';
import * as socketApi from './common/wssocket';
import store from './store';
import { createSSRApp } from 'vue'
+// #ifdef H5
+import * as recorder from './common/recorder-h5';
+// #endif
+// #ifndef H5
+import * as recorder from './common/recorder-app';
+// #endif
+
export function createApp() {
const app = createSSRApp(App)
@@ -15,6 +22,7 @@ export function createApp() {
app.config.globalProperties.$emo = emotion;
app.config.globalProperties.$enums = enums;
app.config.globalProperties.$date = date;
+ app.config.globalProperties.$rc = recorder;
return {
app
}
diff --git a/im-uniapp/manifest.json b/im-uniapp/manifest.json
index 29db5e8..e5d7646 100644
--- a/im-uniapp/manifest.json
+++ b/im-uniapp/manifest.json
@@ -2,8 +2,8 @@
"name" : "盒子IM",
"appid" : "__UNI__69DD57A",
"description" : "",
- "versionName" : "1.0.6",
- "versionCode" : 106,
+ "versionName" : "1.0.7",
+ "versionCode" : 107,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
@@ -100,6 +100,7 @@
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wxda94f40bfad0262c",
+ "libVersion": "latest",
"setting" : {
"urlCheck" : false
},
diff --git a/im-uniapp/package.json b/im-uniapp/package.json
index bb25321..680d46c 100644
--- a/im-uniapp/package.json
+++ b/im-uniapp/package.json
@@ -1,6 +1,10 @@
{
+ "name": "盒子IM",
"uni-app": {
- "scripts": {
- }
+ "scripts": {}
+ },
+ "dependencies": {
+ "js-audio-recorder": "^1.0.7",
+ "recorder-core": "^1.3.23122400"
}
-}
\ No newline at end of file
+}
diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue
index ff6d7d1..ffd421b 100644
--- a/im-uniapp/pages/chat/chat-box.vue
+++ b/im-uniapp/pages/chat/chat-box.vue
@@ -9,8 +9,7 @@
-
@@ -29,15 +28,18 @@
-
+
+
+
+
-
-
+
+
@@ -69,22 +71,25 @@
文件
-
+
- 语音输入
-
+ 语音消息
+
回执消息
-
+
+
+
视频通话
-
+
语音通话
+
@@ -101,6 +106,7 @@