Просмотр исходного кода

feat:移动端支持音视频通话

xsx 2 лет назад
Родитель
Сommit
862c6f2b53

+ 3 - 3
im-platform/src/main/java/com/bx/implatform/controller/WebrtcController.java

@@ -21,8 +21,8 @@ public class WebrtcController {
 
     @ApiOperation(httpMethod = "POST", value = "呼叫视频通话")
     @PostMapping("/call")
-    public Result call(@RequestParam Long uid, @RequestBody String offer) {
-        webrtcService.call(uid, offer);
+    public Result call(@RequestParam Long uid, @RequestParam(defaultValue = "video") String mode, @RequestBody String offer) {
+        webrtcService.call(uid, mode, offer);
         return ResultUtils.success();
     }
 
@@ -65,7 +65,7 @@ public class WebrtcController {
 
     @PostMapping("/candidate")
     @ApiOperation(httpMethod = "POST", value = "同步candidate")
-    public Result forwardCandidate(@RequestParam Long uid, @RequestBody String candidate) {
+    public Result candidate(@RequestParam Long uid, @RequestBody String candidate) {
         webrtcService.candidate(uid, candidate);
         return ResultUtils.success();
     }

+ 7 - 2
im-platform/src/main/java/com/bx/implatform/enums/MessageType.java

@@ -53,10 +53,15 @@ public enum MessageType {
      * 消息加载标记
      */
     LOADDING(30,"加载中"),
+
+    /**
+     * 语音呼叫
+     */
+    RTC_CALL_VOICE(100, "语音呼叫"),
     /**
-     * 呼叫
+     * 视频呼叫
      */
-    RTC_CALL(101, "呼叫"),
+    RTC_CALL_VIDEO(101, "视频呼叫"),
     /**
      * 接受
      */

+ 2 - 2
im-platform/src/main/java/com/bx/implatform/service/IWebrtcService.java

@@ -12,9 +12,9 @@ import java.util.List;
  */
 public interface IWebrtcService {
 
-    void call(Long uid, String offer);
+    void call(Long uid, String mode,String offer);
 
-    void accept(Long uid, @RequestBody String answer);
+    void accept(Long uid,  String answer);
 
     void reject(Long uid);
 

+ 5 - 3
im-platform/src/main/java/com/bx/implatform/service/impl/WebrtcServiceImpl.java

@@ -33,7 +33,7 @@ public class WebrtcServiceImpl implements IWebrtcService {
     private final ICEServerConfig iceServerConfig;
 
     @Override
-    public void call(Long uid, String offer) {
+    public void call(Long uid, String mode, String offer) {
         UserSession session = SessionContext.getSession();
         if (!imClient.isOnline(uid)) {
             throw new GlobalException("对方目前不在线");
@@ -46,7 +46,8 @@ public class WebrtcServiceImpl implements IWebrtcService {
         redisTemplate.opsForValue().set(key, webrtcSession, 12, TimeUnit.HOURS);
         // 向对方所有终端发起呼叫
         PrivateMessageVO messageInfo = new PrivateMessageVO();
-        messageInfo.setType(MessageType.RTC_CALL.code());
+        MessageType messageType = mode.equals("video") ? MessageType.RTC_CALL_VIDEO : MessageType.RTC_CALL_VOICE;
+        messageInfo.setType(messageType.code());
         messageInfo.setRecvId(uid);
         messageInfo.setSendId(session.getUserId());
         messageInfo.setContent(offer);
@@ -146,6 +147,7 @@ public class WebrtcServiceImpl implements IWebrtcService {
         messageInfo.setType(MessageType.RTC_FAILED.code());
         messageInfo.setRecvId(uid);
         messageInfo.setSendId(session.getUserId());
+        messageInfo.setContent(reason);
 
         IMPrivateMessage<PrivateMessageVO> sendMessage = new IMPrivateMessage<>();
         sendMessage.setSender(new IMUserInfo(session.getUserId(), session.getTerminal()));
@@ -215,7 +217,7 @@ public class WebrtcServiceImpl implements IWebrtcService {
 
     private WebrtcSession getWebrtcSession(Long userId, Long uid) {
         String key = getSessionKey(userId, uid);
-        WebrtcSession webrtcSession = (WebrtcSession) redisTemplate.opsForValue().get(key);
+        WebrtcSession webrtcSession = (WebrtcSession)redisTemplate.opsForValue().get(key);
         if (webrtcSession == null) {
             throw new GlobalException("视频通话已结束");
         }

BIN
im-ui/src/assets/audio/call.wav


+ 20 - 2
im-uniapp/App.vue

@@ -104,8 +104,26 @@
 			},
 			insertPrivateMessage(friend, msg) {
 				// webrtc 信令
-				if (msg.type >= enums.MESSAGE_TYPE.RTC_CALL &&
-					msg.type <= enums.MESSAGE_TYPE.RTC_CANDIDATE) {}
+				if (msg.type >= enums.MESSAGE_TYPE.RTC_CALL_VOICE &&
+					msg.type <= enums.MESSAGE_TYPE.RTC_CANDIDATE) {
+					// 被呼叫,弹出视频页面
+					if(msg.type == enums.MESSAGE_TYPE.RTC_CALL_VOICE 
+						|| msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO){
+						let mode = 	msg.type == enums.MESSAGE_TYPE.RTC_CALL_VIDEO? "video":"voice";
+						let pages = getCurrentPages();
+						let curPage = pages[pages.length-1].route;
+						if(curPage != "pages/chat/chat-video"){
+							const friendInfo = encodeURIComponent(JSON.stringify(friend));
+							uni.navigateTo({
+								url: `/pages/chat/chat-video?mode=${mode}&friend=${friendInfo}&isHost=false`
+							})
+						}
+					}
+					setTimeout(() => {
+						uni.$emit('WS_RTC',msg);
+					},500)
+					return;
+				}
 
 				let chatInfo = {
 					type: 'PRIVATE',

+ 2 - 1
im-uniapp/common/enums.js

@@ -11,7 +11,8 @@ const MESSAGE_TYPE = {
 	TIP_TIME:20,
 	TIP_TEXT:21,
 	LOADDING:30,
-	RTC_CALL: 101,
+	RTC_CALL_VOICE: 100,
+	RTC_CALL_VIDEO: 101,
 	RTC_ACCEPT: 102,
 	RTC_REJECT: 103,
 	RTC_CANCEL: 104,

+ 13 - 0
im-uniapp/hybrid/html/index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="">
+	<head>
+		<meta charset="utf-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge">
+		<meta name="viewport" content="width=device-width,initial-scale=1">
+		<link rel="icon" href="favicon.ico">
+		<title>视频通话</title>
+	</head>
+	<body>
+		<div style="padding-top:10px; text-align: center;font-size: 16px;">音视频通话为付费功能,有需要请联系作者...</div>
+	</body>
+</html>

+ 5 - 2
im-uniapp/pages.json

@@ -1,5 +1,5 @@
 {
-	"lazyCodeLoading":"requiredComponents",
+
 	"pages": [{
 		"path": "pages/login/login"
 	}, {
@@ -16,6 +16,8 @@
 		"path": "pages/common/user-info"
 	}, {
 		"path": "pages/chat/chat-box"
+	},{
+		"path": "pages/chat/chat-video"
 	}, {
 		"path": "pages/friend/friend-add"
 	}, {
@@ -30,7 +32,8 @@
 		"path": "pages/mine/mine-edit"
 	},{
 		"path": "pages/mine/mine-password"
-	}],
+	}
+	],
 	"globalStyle": {
 		"navigationBarTitleText": "盒子IM",
 		"navigationBarTextStyle": "black",

+ 33 - 18
im-uniapp/pages/chat/chat-box.vue

@@ -30,9 +30,9 @@
 		<view class="send-bar">
 			<view class="send-text">
 				<textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false"
-				:placeholder="isReceipt?'[回执消息]':''"
-					:adjust-position="false" @confirm="sendTextMessage()" @keyboardheightchange="onKeyboardheightchange"
-					@input="onTextInput" confirm-type="send" confirm-hold :hold-keyboard="true"></textarea>
+					:placeholder="isReceipt?'[回执消息]':''" :adjust-position="false" @confirm="sendTextMessage()"
+					@keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send" confirm-hold
+					:hold-keyboard="true"></textarea>
 			</view>
 			<view v-if="chat.type=='GROUP'" class="iconfont icon-at" @click="openAtBox()"></view>
 			<view class="iconfont icon-icon_emoji" @click="switchChatTabBox('emo',true)"></view>
@@ -71,14 +71,18 @@
 				<view class="chat-tools-item" @click="showTip()">
 					<view class="tool-icon iconfont icon-microphone"></view>
 					<view class="tool-name">语音输入</view>
-				</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-name">回执消息</view>
 				</view>
-				<view class="chat-tools-item" @click="showTip()">
+				<view class="chat-tools-item"  @click="onVideoCall()">
+					<view class="tool-icon iconfont icon-video"></view>
+					<view class="tool-name">视频通话</view>
+				</view>
+				<view class="chat-tools-item"  @click="onVoiceCall()">
 					<view class="tool-icon iconfont icon-call"></view>
-					<view class="tool-name">呼叫</view>
+					<view class="tool-name">语音通话</view>
 				</view>
 			</view>
 			<scroll-view v-if="chatTabBox==='emo'" class="chat-emotion" scroll-y="true">
@@ -116,17 +120,28 @@
 		},
 		methods: {
 			showTip() {
-				
 				uni.showToast({
 					title: "暂未支持...",
 					icon: "none"
 				})
 			},
-			moveChatToTop(){
+			onVideoCall(){
+				const friendInfo = encodeURIComponent(JSON.stringify(this.friend));
+				uni.navigateTo({
+					url: `/pages/chat/chat-video?mode=video&friend=${friendInfo}&isHost=true`
+				})
+			},
+			onVoiceCall(){
+				const friendInfo = encodeURIComponent(JSON.stringify(this.friend));
+				uni.navigateTo({
+					url: `/pages/chat/chat-video?mode=voice&friend=${friendInfo}&isHost=true`
+				})
+			},
+			moveChatToTop() {
 				let chatIdx = this.$store.getters.findChatIdx(this.chat);
-				this.$store.commit("moveTop",chatIdx);
+				this.$store.commit("moveTop", chatIdx);
 			},
-			switchReceipt(){
+			switchReceipt() {
 				this.isReceipt = !this.isReceipt;
 			},
 			openAtBox() {
@@ -164,12 +179,12 @@
 						icon: "none"
 					});
 				}
-				let receiptText = this.isReceipt? "【回执消息】":"";
+				let receiptText = this.isReceipt ? "【回执消息】" : "";
 				let atText = this.createAtText();
 				let msgInfo = {
 					content: receiptText + this.sendText + atText,
 					atUserIds: this.atUserIds,
-					receipt : this.isReceipt,
+					receipt: this.isReceipt,
 					type: 0
 				}
 				// 填充对方id
@@ -185,7 +200,7 @@
 					msgInfo.sendId = this.$store.state.userStore.userInfo.id;
 					msgInfo.selfSend = true;
 					msgInfo.readedCount = 0,
-					msgInfo.status = this.$enums.MESSAGE_STATUS.UNSEND;
+						msgInfo.status = this.$enums.MESSAGE_STATUS.UNSEND;
 					this.$store.commit("insertMessage", msgInfo);
 					// 会话置顶
 					this.moveChatToTop();
@@ -727,7 +742,7 @@
 			.chat-tools {
 				display: flex;
 				flex-wrap: wrap;
-			
+
 				.chat-tools-item {
 					width: 140rpx;
 					padding: 16rpx;
@@ -736,12 +751,12 @@
 					align-items: center;
 
 					.tool-icon {
-						padding: 18rpx;
-						font-size: 80rpx;
+						padding: 28rpx;
+						font-size: 60rpx;
 						background-color: white;
 						border-radius: 20%;
-						
-						&.active{
+
+						&.active {
 							background-color: #ddd;
 						}
 					}

+ 5 - 1
im-uniapp/static/icon/iconfont.css

@@ -1,6 +1,6 @@
 @font-face {
   font-family: "iconfont"; /* Project id 4272106 */
-  src: url('iconfont.ttf?t=1706027587101') format('truetype');
+  src: url('iconfont.ttf?t=1710059877142') format('truetype');
 }
 
 .iconfont {
@@ -11,6 +11,10 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-video:before {
+  content: "\e685";
+}
+
 .icon-receipt:before {
   content: "\e61a";
 }

BIN
im-uniapp/static/icon/iconfont.ttf