Browse Source

Merge branch 'master' of http://git.dayaedu.com/lex/dy-admin-live

lex-xin 3 years ago
parent
commit
0cf913e69c

+ 13 - 15
src/components/live-broadcast/action-bar.tsx

@@ -91,19 +91,7 @@ export default defineComponent({
             </ElButton>
             <span class={styles['bar-btn-text']}>美颜</span>
           </div> */}
-          <div class={styles['bar-btn']}>
-            <ElButton type="primary" color="transparent">
-              <SvgIcon
-                name="mike"
-                style={{
-                  width: '52px'
-                }}
-              />
-            </ElButton>
-            <span class={styles['bar-btn-text']}>麦克风</span>
-          </div>
-
-          {/* <ElDropdown
+          <ElDropdown
             placement="top"
             onCommand={RuntimeUtils.setSelectMicrophone}
             // @ts-ignore
@@ -115,8 +103,18 @@ export default defineComponent({
               )
             }}
           >
-            <ElButton type="primary">音频设备</ElButton>
-          </ElDropdown> */}
+            <div class={styles['bar-btn']}>
+              <ElButton type="primary" color="transparent">
+                <SvgIcon
+                  name="mike"
+                  style={{
+                    width: '52px'
+                  }}
+                />
+              </ElButton>
+              <span class={styles['bar-btn-text']}>麦克风</span>
+            </div>
+          </ElDropdown>
         </div>
         <div style={{ display: 'flex' }}>
           <div class={styles['bar-btn']}>

+ 3 - 8
src/components/live-broadcast/index.tsx

@@ -36,6 +36,8 @@ export default defineComponent({
         runtime.mediaStreams = mediaStreams
         // runtime.mediaStreamTrack = mediaStreams.getTracks()
         RuntimeUtils.setVideoSrcObject(runtime.videoRef, mediaStreams)
+        await RuntimeUtils.setTrack([cameraVideoTrack], 'camera')
+        await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone')
         const join = await RuntimeUtils.joinRoom('w_3fi4PXQcooe5_VUseReE', RTC.RCLivingType.VIDEO, {
           onMessageReceive(name, content) {
             console.log(name, content)
@@ -44,15 +46,8 @@ export default defineComponent({
             console.log(byServer)
           }
         })
-        if (join.code === RTC.RCRTCCode.SUCCESS && join.room) {
+        if (join.room && join.code === RTC.RCRTCCode.SUCCESS) {
           runtime.joinedRoom = join.room
-          await RuntimeUtils.setTrack([cameraVideoTrack], 'camera')
-          await RuntimeUtils.setTrack([microphoneAudioTrack], 'microphone')
-          const builder = await runtime.joinedRoom?.getMCUConfigBuilder()
-          // @ts-ignore
-          await builder.setOutputVideoRenderMode?.(RTC.MixVideoRenderMode.WHOLE)
-          // @ts-ignore
-          await builder.flush()
         }
       } catch (error) {
         runtime.videoStatus = 'error'

+ 8 - 0
src/components/live-broadcast/message-type.ts

@@ -0,0 +1,8 @@
+/**
+ * 注册多种自定义消息类型
+ */
+
+ import * as RongIMLib from '@rongcloud/imlib-next'
+console.log(RongIMLib.registerMessageType)
+ /** 连麦消息 */
+ export const SeatsCtrl = RongIMLib.registerMessageType('RC:Chatroom:SeatsCtrl ', true, true, [])

+ 80 - 6
src/components/live-broadcast/runtime.ts

@@ -2,8 +2,10 @@ import { reactive, ref, Ref } from 'vue'
 import * as RongIMLib from '@rongcloud/imlib-next'
 import * as RTC from '@rongcloud/plugin-rtc'
 import request from '/src/helpers/request'
+import { state } from '/src/state'
 import event, { LIVE_EVENT_MESSAGE } from './event'
 import { removeMedia } from './helpers'
+// import { SeatsCtrl } from './message-type'
 
 type imConnectStatus = 'connecting' | 'connected' | 'disconnect'
 
@@ -46,6 +48,8 @@ const runtime = reactive({
   lastLikeCount: 0,
   /** 当前活跃的数据流 */
   activeTracks: {} as ActiveTracks,
+  /** 是否允许连麦 */
+  allowSeatsCtrl: true,
 })
 
 export default runtime
@@ -57,6 +61,14 @@ RongIMLib.init({
   appkey: RONG_IM_TOKEN,
 })
 
+// 注册自定义消息类型
+
+// 控制是否允许连麦
+const MessageSeatsCtrl = RongIMLib.registerMessageType('RC:Chatroom:SeatsCtrl', true, true)
+
+// 控制是否允许发言
+const MessageChatBan = RongIMLib.registerMessageType('RC:Chatroom:ChatBan', true, true)
+
 type MessageProps = {
   messageType: 'RC:Chatroom:Welcome' | 'RC:TxtMsg' | 'RC:Chatroom:Barrage' | 'RC:Chatroom:Like',
   content: any,
@@ -235,25 +247,29 @@ export const getTrack = async (trackType: TrackType): Promise<RTC.RCLocalTrack>
  * 添加视频流,会同步修改当先视频与推送的流
  * @param track
  */
-export const setTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType) => {
+export const setTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType, needPublish = true) => {
   for (const track of tracks) {
     // @ts-ignore
     await runtime.mediaStreams?.addTrack(track._msTrack)
     runtime.activeTracks[trackType] = track
   }
-  await runtime.joinedRoom?.publish(tracks)
+  if (needPublish) {
+    await runtime.joinedRoom?.publish(tracks)
+  }
 }
 /**
  * 删除视频流,会同步修改当先视频与推送的流
  * @param track
  */
-export const removeTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType) => {
+export const removeTrack = async (tracks: RTC.RCLocalTrack[], trackType: TrackType, needPublish = true) => {
   for (const track of tracks) {
     // @ts-ignore
     await runtime.mediaStreams?.removeTrack(track._msTrack)
     runtime.activeTracks[trackType] = null
   }
-  await runtime.joinedRoom?.unpublish(tracks)
+  if (needPublish) {
+    await runtime.joinedRoom?.unpublish(tracks)
+  }
 }
 
 export const joinRoom = async (roomId: string, type: RTC.RCLivingType, listenEvents: RTC.IRoomEventListener | null) => {
@@ -270,7 +286,19 @@ export const joinRoom = async (roomId: string, type: RTC.RCLivingType, listenEve
 
 export const startLive = async () => {
   if (runtime.videoStatus !== 'stream') throw Error('当前无视频流')
-
+  const room = runtime.joinedRoom
+  if (room) {
+    const microphoneAudioTrack = await getTrack('microphone')
+    const cameraVideoTrack = await getTrack('camera')
+    await setTrack([cameraVideoTrack], 'camera')
+    runtime.videoStatus = 'liveing'
+    await setTrack([microphoneAudioTrack], 'microphone')
+    const builder = await runtime.joinedRoom?.getMCUConfigBuilder()
+    // @ts-ignore
+    await builder.setOutputVideoRenderMode?.(RTC.MixVideoRenderMode.WHOLE)
+    // @ts-ignore
+    await builder.flush()
+  }
 }
 
 /**
@@ -279,6 +307,14 @@ export const startLive = async () => {
 export const closeLive = async () => {
   removeMedia(runtime.mediaStreams, runtime.mediaStreamTrack)
   runtime.videoStatus = 'stopped'
+  for (const key in runtime.activeTracks) {
+    if (Object.prototype.hasOwnProperty.call(runtime.activeTracks, key)) {
+      const track = runtime.activeTracks[key as TrackType] as RTC.RCLocalTrack
+      if (track) {
+        removeTrack([track], key as TrackType)
+      }
+    }
+  }
 }
 
 /**
@@ -293,6 +329,44 @@ export const loopSyncLike = async () => {
   }
   setTimeout(() => {
     loopSyncLike()
-  }, 1000 * 60 * 5)
+  }, 1000 * 60)
 }
 
+type SendMessageType = 'text' | 'image' | 'audio' | 'video' | 'file' | 'SeatsCtrl' | 'ChatBan'
+
+export const getSendMessageUser = () => {
+  return {
+    id: state.user?.id,
+    name: state.user?.realName,
+    userId: state.user?.id,
+    userName: state.user?.realName,
+  }
+}
+
+/**
+ *
+ * @param msg 消息内容
+ * @param type 消息类型
+ * @returns null 或者 发送消息的结果
+ */
+export const sendMessage = async (msg: any, type: SendMessageType = 'text') => {
+  let message: RongIMLib.BaseMessage<unknown> | null = null
+  if (!msg) return
+  const conversation = {
+    conversationType: RongIMLib.ConversationType.CHATROOM,
+    targetId: runtime.joinedRoom?._roomId as string,
+  }
+  if (type === 'text') {
+    message = new RongIMLib.TextMessage({
+      user: getSendMessageUser(),
+      content: msg
+    })
+  } else if (type === 'SeatsCtrl') {
+    message = new MessageSeatsCtrl(msg)
+  } else if (type === 'ChatBan') {
+    message = new MessageChatBan(msg)
+  }
+  if (!message) return
+  console.log(msg)
+  await RongIMLib.sendMessage(conversation, message)
+}

+ 12 - 3
src/components/live-message/message.tsx

@@ -1,4 +1,5 @@
 import { defineComponent } from "vue";
+import runtime, * as RuntimeUtils from '/src/components/live-broadcast/runtime'
 import styles from './message.module.less';
 
 
@@ -10,14 +11,22 @@ export default defineComponent({
       options: 'ALL' as optionsType
     }
   },
+  methods: {
+    SeatsCtrl() {
+      RuntimeUtils.sendMessage({seatBan: !runtime.allowSeatsCtrl, ...RuntimeUtils.getSendMessageUser()}, 'SeatsCtrl')
+    },
+    ChatBan() {
+      RuntimeUtils.sendMessage({chatBan: !runtime.allowSeatsCtrl, ...RuntimeUtils.getSendMessageUser()}, 'ChatBan')
+    },
+  },
   render() {
     return (
       <div class={styles.message}>
         <div class={styles.buttonGroup}>
-          <div class={[this.options === 'ALL' ? styles.active : null, styles.btn]}>全体禁言</div>
-          <div class={styles.btn}>禁止连麦</div>
+          <div onClick={this.SeatsCtrl} class={[this.options === 'ALL' ? styles.active : null, styles.btn]}>全体禁言</div>
+          <div onClick={this.ChatBan} class={styles.btn}>禁止连麦</div>
         </div>
       </div>
     )
   }
-})
+})

+ 6 - 1
src/components/live-message/model/look-model.tsx

@@ -1,4 +1,5 @@
 import { defineComponent } from "vue";
+import * as RuntimeUtils from '/src/components/live-broadcast/runtime'
 import styles from './index.module.less'
 import event, { LIVE_EVENT_MESSAGE } from '/src/components/live-broadcast/event';
 import { state } from '/src/state'
@@ -59,6 +60,10 @@ export default defineComponent({
             <div class={styles.itemInfo} >
               <div class={styles.itemName}>
                 <p class={styles.userName}>{item.name}</p>
+                <a href="javascript:;" onClick={() => RuntimeUtils.sendMessage(
+                  {seatBan:false, ...RuntimeUtils.getSendMessageUser()},
+                  'SeatsCtrl'
+                )}>上麦</a>
               </div>
             </div>
           </div>
@@ -66,4 +71,4 @@ export default defineComponent({
       </div>
     )
   }
-})
+})

+ 9 - 3
src/components/live-message/send-message.tsx

@@ -1,16 +1,22 @@
 import { defineComponent } from "vue";
 import { ElInput, ElButton } from "element-plus";
+import runtime, * as RuntimeUtils from "/src/components/live-broadcast/runtime";
 import styles from "./send-message.module.less";
 
 export default defineComponent({
+  data() {
+    return {
+      message: ''
+    }
+  },
   render() {
     return (
       <div class={styles.sendMessage}>
         <div class={styles.form}>
-          <ElInput placeholder="请输入消息" />
-          <ElButton round type="primary">发送</ElButton>
+          <ElInput modelValue={this.message} onInput={val => this.message = val} placeholder="请输入消息" />
+          <ElButton onClick={() => RuntimeUtils.sendMessage(this.message)} round type="primary">发送</ElButton>
         </div>
       </div>
     )
   }
-});
+});