Prechádzať zdrojové kódy

1.修复会话记录丢失的bug
2.app端增加消息复制菜单
3.移除多人通话相关代码

xsx 1 rok pred
rodič
commit
48acf02dbb

+ 6 - 10
.gitignore

@@ -3,16 +3,12 @@
 /im-server/im-server.iml
 /im-platform/im-platform.iml
 /im-client/im-client.iml
-/im-platform/src/main/resources/application-prod.yml
-/im-platform/src/main/resources/logback-prod.xml
-/im-server/src/main/resources/application-prod.yml
-/im-server/src/main/resources/logback-prod.xml
 /im-common/im-common.iml
+/im-server/target/
+/im-platform/target/
+/im-client/target/
+/im-common/itarget/
+/im-web/node_modules/
 /im-uniapp/node_modules/
-/im-web/package-lock.json
-/im-uniapp/unpackage/
-/im-uniapp/hybrid/
 /im-uniapp/package-lock.json
-/im-web/src/components/rtc/LocalVideo.vue
-/im-web/src/components/rtc/RemoteVideo.vue
-/im-web/src/components/rtc/RtcGroupAcceptor.vue
+/im-uniapp/unpackage/

+ 2 - 2
im-uniapp/.env.js

@@ -2,8 +2,8 @@
 const ENV = "DEV";
 const UNI_APP = {}
 if(ENV=="DEV"){
-	UNI_APP.BASE_URL = "http://127.0.0.1:8888";
-	UNI_APP.WS_URL = "ws://127.0.0.1:8878/im";
+	UNI_APP.BASE_URL = "http://192.168.43.199:8888";
+	UNI_APP.WS_URL = "ws://192.168.43.199:8878/im";
 	// H5 走本地代理解决跨域问题
 	// #ifdef H5
 		UNI_APP.BASE_URL = "/api";

+ 1 - 1
im-uniapp/App.vue

@@ -1,5 +1,5 @@
 <script>
-	import App from './App'
+	import App from './App' 
 	import http from './common/request';
 	import * as msgType from './common/messageType';
 	import * as enums from './common/enums';

+ 14 - 7
im-uniapp/components/chat-message-item/chat-message-item.vue

@@ -56,7 +56,7 @@
 						</view>
 					</pop-menu>
 					<pop-menu v-if="isAction" :items="menuItems" @select="onSelectMenu">
-						<view class="chat-realtime chat-msg-text"  @click="$emit('call')">
+						<view class="chat-realtime chat-msg-text" @click="$emit('call')">
 							<text v-if="msgInfo.type==$enums.MESSAGE_TYPE.ACT_RT_VOICE"
 								class="iconfont icon-chat-voice"></text>
 							<text v-if="msgInfo.type==$enums.MESSAGE_TYPE.ACT_RT_VIDEO"
@@ -182,12 +182,13 @@
 			},
 			menuItems() {
 				let items = [];
-				items.push({
-					key: 'DELETE',
-					name: '删除',
-					icon: 'trash',
-					color: '#e64e4e'
-				});
+				if (this.msgInfo.type == this.$enums.MESSAGE_TYPE.TEXT) {
+					items.push({
+						key: 'COPY',
+						name: '复制',
+						icon: 'bars'
+					});
+				}
 				if (this.msgInfo.selfSend && this.msgInfo.id > 0) {
 					items.push({
 						key: 'RECALL',
@@ -195,6 +196,12 @@
 						icon: 'refreshempty'
 					});
 				}
+				items.push({
+					key: 'DELETE',
+					name: '删除',
+					icon: 'trash',
+					color: '#e64e4e'
+				});
 				if (this.msgInfo.type == this.$enums.MESSAGE_TYPE.FILE) {
 					items.push({
 						key: 'DOWNLOAD',

+ 5 - 1
im-uniapp/components/pop-menu/pop-menu.vue

@@ -7,7 +7,7 @@
 		<view v-if="isShowMenu" class="pop-menu" @tap="onClose()" @contextmenu.prevent=""></view>
 		<view v-if="isShowMenu" class="menu" :style="menuStyle">
 			<view class="menu-item"  v-for="(item) in items" :key="item.key"  @click.prevent="onSelectMenu(item)">
-				<uni-icons :type="item.icon" :style="itemStyle(item)" size="22"></uni-icons>
+				<uni-icons class="menu-icon" :type="item.icon" :style="itemStyle(item)" size="22"></uni-icons>
 				<text :style="itemStyle(item)"> {{item.name}}</text>
 			</view>
 		</view>
@@ -110,6 +110,10 @@
 			padding: 10px;
 			justify-content: center;
 			border-bottom: 1px solid #d0d0d8;
+			
+			.menu-icon {
+				margin-right: 10rpx;
+			}
 		}
 	}
 

+ 11 - 1
im-uniapp/hybrid/html/rtc-group/index.html

@@ -8,6 +8,16 @@
 		<title>语音通话</title>
 	</head>
 	<body>
-		<div style="padding-top:10px; text-align: center;font-size: 16px;">音视频通话功能需升级至商业版,如有需要请联系作者...</div>
+		<div style="padding-top:10px; text-align: center;font-size: 16px;">
+			音视频通话功能属于付费功能,如有需要请联系作者购买商业版源码...
+		</div>
+		<div style="padding-top:50px; text-align: center;font-size: 16px;">
+			点击下方文档了解详细信息:
+		</div>
+		<div style="padding-top:10px; text-align: center;font-size: 16px;">
+			<a href="https://www.yuque.com/u1475064/imk5n2/qtezcg32q1d0dr29" target="_blank">
+				盒子IM商业版付费说明
+			</a>
+		</div>
 	</body>
 </html>

+ 11 - 1
im-uniapp/hybrid/html/rtc-private/index.html

@@ -8,6 +8,16 @@
 		<title>视频通话</title>
 	</head>
 	<body>
-		<div style="padding-top:10px; text-align: center;font-size: 16px;">音视频通话功能需升级至商业版,如有需要请联系作者...</div>
+		<div style="padding-top:10px; text-align: center;font-size: 16px;">
+			音视频通话功能属于付费功能,如有需要请联系作者购买商业版源码...
+		</div>
+		<div style="padding-top:50px; text-align: center;font-size: 16px;">
+			点击下方文档了解详细信息:
+		</div>
+		<div style="padding-top:10px; text-align: center;font-size: 16px;">
+			<a href="https://www.yuque.com/u1475064/imk5n2/qtezcg32q1d0dr29" target="_blank">
+				盒子IM商业版付费说明
+			</a>
+		</div>
 	</body>
 </html>

+ 49 - 49
im-uniapp/pages/chat/chat-box.vue

@@ -9,8 +9,8 @@
 			<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop"
 				:scroll-into-view="'chat-item-'+scrollMsgIdx">
 				<view v-if="chat" v-for="(msgInfo,idx) in chat.messages" :key="idx">
-					<chat-message-item v-if="idx>=showMinIdx" :headImage="headImage(msgInfo)"
-						@call="onRtCall(msgInfo)" :showName="showName(msgInfo)" @recall="onRecallMessage"
+					<chat-message-item v-if="idx>=showMinIdx" :headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)"
+						:showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage"
 						@delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile"
 						:id="'chat-item-'+idx" :msgInfo="msgInfo" :groupMembers="groupMembers">
 					</chat-message-item>
@@ -50,47 +50,46 @@
 				<view class="chat-tools-item">
 					<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore"
 						:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail">
-						<view class="tool-icon iconfont icon-picture" ></view>
+						<view class="tool-icon iconfont icon-picture"></view>
 					</image-upload>
 					<view class="tool-name">相册</view>
 				</view>
 				<view class="chat-tools-item">
 					<image-upload sourceType="camera" :onBefore="onUploadImageBefore" :onSuccess="onUploadImageSuccess"
 						:onError="onUploadImageFail">
-						<view class="tool-icon iconfont icon-camera" ></view>
+						<view class="tool-icon iconfont icon-camera"></view>
 					</image-upload>
 					<view class="tool-name">拍摄</view>
 				</view>
-				
+
 				<view class="chat-tools-item">
 					<file-upload :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess"
 						:onError="onUploadFileFail">
-						<view class="tool-icon iconfont icon-folder" ></view>
+						<view class="tool-icon iconfont icon-folder"></view>
 					</file-upload>
 					<view class="tool-name">文件</view>
 				</view>
-		
+
 				<view class="chat-tools-item" @click="onRecorderInput()">
-					<view class="tool-icon iconfont icon-microphone" ></view>
+					<view class="tool-icon iconfont icon-microphone"></view>
 					<view class="tool-name">语音消息</view>
 				</view>
 				<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="switchReceipt()">
-					<view class="tool-icon iconfont icon-receipt" 
-						:class="isReceipt?'active':''"></view>
+					<view class="tool-icon iconfont icon-receipt" :class="isReceipt?'active':''"></view>
 					<view class="tool-name">回执消息</view>
 				</view>
 				<!-- #ifndef MP-WEIXIN -->
 				<!-- 音视频不支持小程序 -->
 				<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVideo()">
-					<view class="tool-icon iconfont icon-video" ></view>
+					<view class="tool-icon iconfont icon-video"></view>
 					<view class="tool-name">视频通话</view>
 				</view>
 				<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVoice()">
-					<view class="tool-icon iconfont icon-call" ></view>
+					<view class="tool-icon iconfont icon-call"></view>
 					<view class="tool-name">语音通话</view>
 				</view>
 				<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="onGroupVideo()">
-					<view class="tool-icon iconfont icon-call" ></view>
+					<view class="tool-icon iconfont icon-call"></view>
 					<view class="tool-name">语音通话</view>
 				</view>
 				<!-- #endif -->
@@ -109,8 +108,7 @@
 			@complete="onAtComplete"></chat-at-box>
 		<!-- 群语音通话时选择成员 -->
 		<!-- #ifndef MP-WEIXIN -->
-		<group-member-selector ref="selBox" :members="groupMembers"
-			:maxSize="configStore.webrtc.maxChannel"
+		<group-member-selector ref="selBox" :members="groupMembers" :maxSize="configStore.webrtc.maxChannel"
 			@complete="onInviteOk"></group-member-selector>
 		<group-rtc-join ref="rtcJoin" :groupId="group.id"></group-rtc-join>
 		<!-- #endif -->
@@ -136,8 +134,8 @@
 				keyboardHeight: 322,
 				atUserIds: [],
 				needScrollToBottom: false, // 需要滚动到底部 
-				showMinIdx: 0, 	// 下标小于showMinIdx的消息不显示,否则可能很卡
-				reqQueue: [], 	// 请求队列
+				showMinIdx: 0, // 下标小于showMinIdx的消息不显示,否则可能很卡
+				reqQueue: [], // 请求队列
 				isSending: false // 是否正在发送请求
 			}
 		},
@@ -189,23 +187,13 @@
 				})
 			},
 			onGroupVideo() {
-				this.$http({
-					url: "/webrtc/group/info?groupId="+this.group.id,
-					method: 'GET'
-				}).then((rtcInfo)=>{
-					if(rtcInfo.isChating){
-						// 已在通话中,可以直接加入通话
-						this.$refs.rtcJoin.open(rtcInfo);
-					}else {
-						// 邀请成员发起通话
-						let ids = [this.mine.id];
-						this.$refs.selBox.init(ids, ids);
-						this.$refs.selBox.open();
-					}
-				})
+				// 邀请成员发起通话
+				let ids = [this.mine.id];
+				this.$refs.selBox.init(ids, ids);
+				this.$refs.selBox.open();
 			},
 			onInviteOk(ids) {
-				if(ids.length < 2){
+				if (ids.length < 2) {
 					return;
 				}
 				let users = [];
@@ -264,7 +252,6 @@
 				}
 			},
 			sendTextMessage() {
-				const timeStamp  = new Date().getTime();
 				if (!this.sendText.trim() && this.atUserIds.length == 0) {
 					return uni.showToast({
 						title: "不能发送空白信息",
@@ -283,10 +270,8 @@
 				// 填充对方id
 				this.fillTargetId(msgInfo, this.chat.targetId);
 				this.sendMessageRequest(msgInfo).then((m) => {
-					console.log("请求耗时:",new Date().getTime()-timeStamp)
 					m.selfSend = true;
 					this.chatStore.insertMessage(m);
-					console.log("insertMessage耗时:",new Date().getTime()-timeStamp)
 					// 会话置顶
 					this.moveChatToTop();
 				}).finally(() => {
@@ -368,6 +353,7 @@
 					this.showKeyBoard = true;
 					this.switchChatTabBox('none', false)
 					this.keyboardHeight = this.rpxTopx(e.detail.height);
+					this.scrollToBottom();
 				} else {
 					this.showKeyBoard = false;
 				}
@@ -505,6 +491,17 @@
 					}
 				})
 			},
+			onCopyMessage(msgInfo) {
+				uni.setClipboardData({
+					data: msgInfo.content,
+					success: () => {
+						uni.showToast({ title: '已复制', icon: 'none' });
+					},
+					fail: () => {
+						uni.showToast({ title: '复制失败', icon: 'none' });
+					}
+				});
+			},
 			onDownloadFile(msgInfo) {
 				let url = JSON.parse(msgInfo.content).url;
 				uni.downloadFile({
@@ -622,14 +619,14 @@
 				let px = info.windowWidth * rpx / 750;
 				return Math.floor(rpx);
 			},
-			sendMessageRequest(msgInfo){
-				return  new Promise((resolve,reject)=>{
+			sendMessageRequest(msgInfo) {
+				return new Promise((resolve, reject) => {
 					// 请求入队列,防止请求"后发先至",导致消息错序
-					this.reqQueue.push({msgInfo,resolve,reject});
+					this.reqQueue.push({ msgInfo, resolve, reject });
 					this.processReqQueue();
 				})
 			},
-			processReqQueue(){
+			processReqQueue() {
 				if (this.reqQueue.length && !this.isSending) {
 					this.isSending = true;
 					const reqData = this.reqQueue.shift();
@@ -637,18 +634,18 @@
 						url: this.messageAction,
 						method: 'post',
 						data: reqData.msgInfo
-					}).then((res)=>{
+					}).then((res) => {
 						reqData.resolve(res)
-					}).catch((e)=>{
+					}).catch((e) => {
 						reqData.reject(e)
-					}).finally(()=>{
+					}).finally(() => {
 						this.isSending = false;
 						// 发送下一条请求
 						this.processReqQueue();
 					})
 				}
 			},
-			generateId(){
+			generateId() {
 				// 生成临时id
 				return String(new Date().getTime()) + String(Math.floor(Math.random() * 1000));
 			}
@@ -706,10 +703,10 @@
 				// 接收到消息时滚动到底部
 				if (newSize > oldSize) {
 					let pages = getCurrentPages();
-					let curPage = pages[pages.length-1].route;
-					if(curPage == "pages/chat/chat-box"){
+					let curPage = pages[pages.length - 1].route;
+					if (curPage == "pages/chat/chat-box") {
 						this.scrollToBottom();
-					}else {
+					} else {
 						this.needScrollToBottom = true;
 					}
 				}
@@ -743,8 +740,8 @@
 			// 复位回执消息
 			this.isReceipt = false;
 		},
-		onShow(){
-			if(this.needScrollToBottom){
+		onShow() {
+			if (this.needScrollToBottom) {
 				// 页面滚到底部
 				this.scrollToBottom();
 				this.needScrollToBottom = false;
@@ -839,6 +836,7 @@
 			border: #dddddd solid 1px;
 			background-color: #f7f8fd;
 			height: 80rpx;
+
 			.iconfont {
 				font-size: 68rpx;
 				margin: 6rpx;
@@ -857,6 +855,7 @@
 				border-radius: 20rpx;
 				font-size: 30rpx;
 				box-sizing: border-box;
+
 				.send-text-area {
 					width: 100%;
 				}
@@ -883,13 +882,14 @@
 					display: flex;
 					flex-direction: column;
 					align-items: center;
-						
+
 					.tool-icon {
 						padding: 28rpx;
 						font-size: 60rpx;
 						border-radius: 20%;
 						background-color: white;
 						color: black;
+
 						&.active {
 							background-color: #ddd;
 						}

BIN
im-uniapp/static/logo/logo.png


+ 6 - 3
im-uniapp/store/chatStore.js

@@ -292,15 +292,18 @@ export default defineStore('chatStore', {
 				this.refreshChats()
 			}
 		},
-		refreshChats(state) {
+		refreshChats() {
+			if(!cacheChats){
+				return;
+			}
 			// 排序
 			cacheChats.sort((chat1, chat2) => {
 				return chat2.lastSendTime - chat1.lastSendTime;
 			});
 			// 将消息一次性装载回来
 			this.chats = cacheChats;
-			// 断线重连后不能使用缓存模式,否则会导致聊天窗口的消息不刷新
-			cacheChats = this.chats;
+			// 清空缓存
+			cacheChats = null;
 			this.saveToStorage();
 		},
 		saveToStorage(state) {

+ 4 - 15
im-web/src/components/chat/ChatBox.vue

@@ -293,21 +293,10 @@
 				this.$eventBus.$emit("openPrivateVideo", rtcInfo);
 			},
 			onGroupVideo() {
-				this.$http({
-					url: "/webrtc/group/info?groupId=" + this.group.id,
-					method: 'GET'
-				}).then((rtcInfo) => {
-					if (rtcInfo.isChating) {
-						// 已在通话中,可以直接加入通话
-						this.$refs.rtcJoin.open(rtcInfo);
-					} else {
-						// 邀请成员发起通话
-						let ids = [this.mine.id];
-						let maxChannel = this.$store.state.configStore.webrtc.maxChannel;
-						this.$refs.rtcSel.open(maxChannel, ids, ids);
-					}
-				})
-
+				// 邀请成员发起通话
+				let ids = [this.mine.id];
+				let maxChannel = this.$store.state.configStore.webrtc.maxChannel;
+				this.$refs.rtcSel.open(maxChannel, ids, ids);
 			},
 			onInviteOk(members) {
 				if (members.length < 2) {

+ 1 - 1
im-web/src/components/rtc/RtcGroupVideo.vue

@@ -3,7 +3,7 @@
 			   :visible.sync="isShow" width="50%">
 		<div class='rtc-group-video'>
 			<div style="padding-top:30px;font-weight: 600; text-align: center;font-size: 16px;">
-				多人音视频通话需升级至商业版,如有需要请联系作者购买...
+				多人音视频通话属于付费功能,如有需要请联系作者购买商业版源码...
 			</div>
 			<div style="padding-top:50px; text-align: center;font-size: 16px;">
 				点击下方文档了解详细信息:

+ 5 - 2
im-web/src/store/chatStore.js

@@ -280,14 +280,17 @@ export default {
 			}
 		},
 		refreshChats(state) {
+			if(!cacheChats){
+				return;
+			}
 			// 排序
 			cacheChats.sort((chat1, chat2) => {
 				return chat2.lastSendTime - chat1.lastSendTime;
 			});
 			// 将消息一次性装载回来
 			state.chats = cacheChats;
-			// 断线重连后不能使用缓存模式,否则会导致聊天窗口的消息不刷新
-			cacheChats = state.chats;
+			// 清空缓存
+			cacheChats = null;
 			this.commit("saveToStorage");
 		},
 		saveToStorage(state) {