|
@@ -0,0 +1,801 @@
|
|
|
|
+<template>
|
|
|
|
+ <div id="detailInfo">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="24" class="info">
|
|
|
|
+ <el-col :span="4" class="left">
|
|
|
|
+ <el-col :span="24" class="leftTop">
|
|
|
|
+ <el-image :src="roomdetail.filedir"></el-image>
|
|
|
|
+ <p>{{ roomdetail.title }}</p>
|
|
|
|
+ <p>{{ roomdetail.content }}</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="24" class="leftDown">
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="shexiangBtn()">
|
|
|
|
+ <i class="iconfont iconshexiangtou"></i>
|
|
|
|
+ <p>摄像头</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="tianchongBtn()">
|
|
|
|
+ <i class="iconfont iconmaikefeng-tianchong"></i>
|
|
|
|
+ <p>麦克风</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="chatBtn()">
|
|
|
|
+ <i class="el-icon-user"></i>
|
|
|
|
+ <p>聊天</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="24" class="leftDown">
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="lookuserBtn()">
|
|
|
|
+ <i class="el-icon-user"></i>
|
|
|
|
+ <p>成员</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="queBtn()">
|
|
|
|
+ <i class="el-icon-question"></i>
|
|
|
|
+ <p>问卷</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="8" class="btn" @click.native="queCloseBtn()">
|
|
|
|
+ <i class="el-icon-circle-close"></i>
|
|
|
|
+ <p>停卷</p>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="20" class="right">
|
|
|
|
+ <el-col :span="24" class="rightTop">
|
|
|
|
+ <span @click="liveon"><i class="iconfont iconshexiangtou"></i>直播</span>
|
|
|
|
+ <span v-show="zjrshow" @click="livezhuchi"><i class="iconfont iconshexiangtou"></i>主持</span>
|
|
|
|
+ <span @click="liveclose"><i class="el-icon-switch-button"></i>关闭直播</span>
|
|
|
|
+ <span @click="shareon"><i class="iconfont iconfenxiang"></i>屏幕</span>
|
|
|
|
+ <span @click="shareclose"><i class="iconfont iconfenxiang"></i>关闭分享</span>
|
|
|
|
+ <span><el-switch @change="recordclick" v-model="isrecord" active-text="录制" inactive-text="停录"> </el-switch></span>
|
|
|
|
+ <span @click="dismissroomClick"><i class="iconfont iconfenxiang"></i>解散房间</span>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="2" class="noVideo"> </el-col>
|
|
|
|
+ <el-col :span="20" class="video">
|
|
|
|
+ <el-col :span="24" class="videoMeet">
|
|
|
|
+ <el-col :span="18" class="one">
|
|
|
|
+ <div id="main-video" class="video-box col-div" style="justify-content: flex-end"></div>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="6" class="two">
|
|
|
|
+ <el-col v-show="zjrshow" :span="24" class="twoOne" v-for="(item, index) in zjrList" :key="index">
|
|
|
|
+ <el-col :span="14">
|
|
|
|
+ <div :id="forOtherId(item.zjrid)" class="video-box col-div othevideo" style="justify-content: flex-end"></div>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="10">
|
|
|
|
+ <p>
|
|
|
|
+ <span>{{ item.zjrname }}</span>
|
|
|
|
+ <span>
|
|
|
|
+ <el-button type="danger" size="mini" @click="zjrChange(item.zjrid)">主讲</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ </p>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="2" class="noVideo"></el-col>
|
|
|
|
+ <el-col :span="24" class="rightDown">
|
|
|
|
+ <!-- 开始直播 -->
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ <el-dialog title="摄像头" :visible.sync="shexiangDia" width="30%" :before-close="handleClose">
|
|
|
|
+ <el-select @change="cameraChange" v-model="cameraId" filterable placeholder="请选择摄像头">
|
|
|
|
+ <el-option v-for="item in cameras" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ <el-dialog title="麦克风" :visible.sync="tianchongDia" width="30%" :before-close="handleClose">
|
|
|
|
+ <el-select @change="micrChange" v-model="microphoneId" filterable placeholder="请选择麦克风">
|
|
|
|
+ <el-option v-for="item in microphones" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ <el-dialog title="讨论" :visible.sync="chatDia" width="50%" :before-close="handleClose">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="24" class="chatList">
|
|
|
|
+ <el-col :span="24" class="list" v-for="(item, index) in dataList" :key="index">
|
|
|
|
+ <p>
|
|
|
|
+ <span :class="item.sendname == user.name ? 'selfColor' : ''">{{ item.sendname }}</span>
|
|
|
|
+ <span>{{ item.content }}</span>
|
|
|
|
+ </p>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="24" class="chatInput">
|
|
|
|
+ <el-col :span="19" class="input">
|
|
|
|
+ <el-input type="textarea" maxlength="5000" show-word-limit v-model="content"></el-input>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="5" class="btn">
|
|
|
|
+ <el-button type="primary" size="mini" @click="chatCreate">发送</el-button>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ <el-dialog title="问卷" :visible.sync="queDia" width="38%" :before-close="handleClose">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="24">
|
|
|
|
+ <el-col :span="12">
|
|
|
|
+ <el-select v-model="queid" filterable placeholder="请选择问卷">
|
|
|
|
+ <el-option v-for="item in questList" :key="item.id" :label="item.name" :value="item.id"> </el-option>
|
|
|
|
+ </el-select>
|
|
|
|
+ </el-col>
|
|
|
|
+ <el-col :span="12" class="btn">
|
|
|
|
+ <el-button type="primary" size="mini" @click="queCreate">发送</el-button>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ <el-dialog title="成员" :visible.sync="lookuserDia" width="60%" height="450px" :before-close="handleClose" :close-on-click-modal="(clo = false)">
|
|
|
|
+ <el-row>
|
|
|
|
+ <el-col :span="24" class="sudoku_row">
|
|
|
|
+ <el-col :span="24" class="sudoku_item" v-for="(item, index) in userList" :key="index">
|
|
|
|
+ <div :id="forId(item.userid)" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
|
|
|
|
+ <p>
|
|
|
|
+ <i class="el-icon-user"></i>
|
|
|
|
+ <span class="selfColor">{{ item.username }}({{ item.isonline === '1' ? '在线' : '离线' }})</span>
|
|
|
|
+ <span v-if="item.switchrole === 'anchor'">
|
|
|
|
+ <el-button type="danger" size="mini" @click="lookuserUpdate(item.id, 'audience')">移除</el-button>
|
|
|
|
+ <el-button type="primary" size="mini" @click="roomshangmai(item.userid)">主讲</el-button>
|
|
|
|
+ </span>
|
|
|
|
+ <span v-else><el-button type="primary" size="mini" @click="lookuserUpdate(item.id, 'anchor')">连麦</el-button></span>
|
|
|
|
+ </p>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </el-dialog>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import Vue from 'vue';
|
|
|
|
+import { mapState, createNamespacedHelpers } from 'vuex';
|
|
|
|
+const { mapActions: gensign } = createNamespacedHelpers('gensign');
|
|
|
|
+const { mapActions: chat } = createNamespacedHelpers('chat');
|
|
|
|
+const { mapActions: room } = createNamespacedHelpers('room');
|
|
|
|
+const { mapActions: lookuser } = createNamespacedHelpers('lookuser');
|
|
|
|
+const { mapActions: roomuser } = createNamespacedHelpers('roomuser');
|
|
|
|
+import TRTC from 'trtc-js-sdk';
|
|
|
|
+export default {
|
|
|
|
+ name: 'detailInfo',
|
|
|
|
+ props: {
|
|
|
|
+ roomInfo: null,
|
|
|
|
+ },
|
|
|
|
+ components: {},
|
|
|
|
+ data: function() {
|
|
|
|
+ return {
|
|
|
|
+ // 摄像头
|
|
|
|
+ shexiangDia: false,
|
|
|
|
+ cameraId: '',
|
|
|
|
+ cameras: [],
|
|
|
|
+ // 麦克风
|
|
|
|
+ tianchongDia: false,
|
|
|
|
+ chatDia: false,
|
|
|
|
+ queDia: false,
|
|
|
|
+ questList: [],
|
|
|
|
+ queid: '',
|
|
|
|
+ microphoneId: '',
|
|
|
|
+ microphones: [],
|
|
|
|
+ client_: '',
|
|
|
|
+ localStream_: '',
|
|
|
|
+ shareClient_: '',
|
|
|
|
+ shareStream_: '',
|
|
|
|
+ sdkAppId_: '1400414461',
|
|
|
|
+ userId_: '',
|
|
|
|
+ userMainId_: '',
|
|
|
|
+ open_: false,
|
|
|
|
+ content: '',
|
|
|
|
+ dataList: [],
|
|
|
|
+ isrecord: false,
|
|
|
|
+ shareid: '',
|
|
|
|
+ userList: [],
|
|
|
|
+ lookuserDia: false,
|
|
|
|
+ index_: 0,
|
|
|
|
+ ov1: '',
|
|
|
|
+ ov2: '',
|
|
|
|
+ ov3: '',
|
|
|
|
+ ov4: '',
|
|
|
|
+ ov5: '',
|
|
|
|
+ ov6: '',
|
|
|
|
+ ov7: '',
|
|
|
|
+ showbtn_: false,
|
|
|
|
+ roomdetail: {},
|
|
|
|
+ zjrList: [],
|
|
|
|
+ zjrshow: false,
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ created() {
|
|
|
|
+ this.getRoomInfo();
|
|
|
|
+ this.initclient();
|
|
|
|
+ this.getDevices();
|
|
|
|
+ this.chatSearch();
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ this.channel();
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ ...gensign(['gensignFetch']),
|
|
|
|
+ ...chat(['query', 'create', 'fetch']),
|
|
|
|
+ ...room({
|
|
|
|
+ roomfetch: 'fetch',
|
|
|
|
+ startrecord: 'startrecord',
|
|
|
|
+ stoprecord: 'stoprecord',
|
|
|
|
+ roomquest: 'roomquest',
|
|
|
|
+ roomquestclose: 'roomquestclose',
|
|
|
|
+ questquery: 'questquery',
|
|
|
|
+ updateanchor: 'updateanchor',
|
|
|
|
+ updateshmai: 'updateshmai',
|
|
|
|
+ switchzjr: 'switchzjr',
|
|
|
|
+ switchzb: 'switchzb',
|
|
|
|
+ switchzp: 'switchzp',
|
|
|
|
+ dismissroom: 'dismissroom',
|
|
|
|
+ }),
|
|
|
|
+ ...lookuser(['lookquery', 'lookupdate']),
|
|
|
|
+ ...roomuser({ roomuserfetch: 'fetch' }),
|
|
|
|
+ // 解散房间
|
|
|
|
+ async dismissroomClick() {
|
|
|
|
+ const info = { roomid: this.id, roomname: this.name };
|
|
|
|
+ let res = await this.dismissroom({ ...info });
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async livezp() {
|
|
|
|
+ const data = {};
|
|
|
|
+ data.id = this.id;
|
|
|
|
+ data.uid = this.user.uid;
|
|
|
|
+ const res = await this.switchzb(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async livezhuchi() {
|
|
|
|
+ const data = {};
|
|
|
|
+ data.id = this.id;
|
|
|
|
+ data.uid = this.user.uid;
|
|
|
|
+ const res = await this.switchzb(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ this.localStream_.unmuteVideo();
|
|
|
|
+ this.localStream_.unmuteAudio();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async zjrChange(zjrid) {
|
|
|
|
+ const data = {};
|
|
|
|
+ data.id = this.id;
|
|
|
|
+ data.switchzjr = zjrid;
|
|
|
|
+ const res = await this.switchzjr(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ this.localStream_.muteVideo();
|
|
|
|
+ this.localStream_.muteAudio();
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async getRoomInfo() {
|
|
|
|
+ const res = await this.roomfetch(this.id);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$set(this, `roomdetail`, res.data);
|
|
|
|
+ if (res.data.anchorid === this.user.uid) {
|
|
|
|
+ this.zjrshow = true;
|
|
|
|
+ }
|
|
|
|
+ for (const elm of res.data.zjr) {
|
|
|
|
+ const ru = await this.roomuserfetch(elm);
|
|
|
|
+ if (this.$checkRes(ru)) {
|
|
|
|
+ const newdata = { zjrid: elm, zjrname: ru.data.name };
|
|
|
|
+ this.zjrList.push(newdata);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async roomshangmai(dataid) {
|
|
|
|
+ const data = {};
|
|
|
|
+ data.id = this.id;
|
|
|
|
+ data.shmaiid = dataid;
|
|
|
|
+ const res = await this.updateshmai(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async queCreate() {
|
|
|
|
+ const data = {};
|
|
|
|
+ data.roomid = this.id;
|
|
|
|
+ data.queid = this.queid;
|
|
|
|
+ const res = await this.roomquest(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async lookuserBtn() {
|
|
|
|
+ this.lookuserDia = true;
|
|
|
|
+ this.lookuserSearch();
|
|
|
|
+ },
|
|
|
|
+ async lookuserSearch({ skip = 0, limit = 1000 } = {}) {
|
|
|
|
+ const info = { roomid: this.id };
|
|
|
|
+ let res = await this.lookquery({ skip, limit, ...info });
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$set(this, `userList`, res.data);
|
|
|
|
+ },
|
|
|
|
+ async lookuserUpdate(_id, _switchrole) {
|
|
|
|
+ console.log(_id);
|
|
|
|
+ let data = {};
|
|
|
|
+ data.id = _id;
|
|
|
|
+ data.switchrole = _switchrole;
|
|
|
|
+ const res = await this.lookupdate(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ this.lookuserSearch();
|
|
|
|
+ } else {
|
|
|
|
+ this.$message.error(res.errmsg);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async recordclick() {
|
|
|
|
+ console.log(this.isrecord);
|
|
|
|
+ if (this.isrecord) {
|
|
|
|
+ const info = { roomid: this.id, roomname: this.name, shareid: this.shareid };
|
|
|
|
+ let res = await this.startrecord({ ...info });
|
|
|
|
+ } else {
|
|
|
|
+ const info = { roomid: this.id, roomname: this.name };
|
|
|
|
+ let res = await this.stoprecord({ ...info });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async chatSearch({ skip = 0, limit = 1000 } = {}) {
|
|
|
|
+ const info = { roomid: this.id };
|
|
|
|
+ let res = await this.query({ skip, limit, ...info });
|
|
|
|
+ this.$set(this, `dataList`, res.data);
|
|
|
|
+ },
|
|
|
|
+ async questSearch({ skip = 0, limit = 1000 } = {}) {
|
|
|
|
+ const info = { status: '1' };
|
|
|
|
+ let res = await this.questquery({ skip, limit, ...info });
|
|
|
|
+ console.log(res);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ this.$set(this, `questList`, res.data);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async chatCreate() {
|
|
|
|
+ let data = {};
|
|
|
|
+ data.roomid = this.id;
|
|
|
|
+ data.type = '0';
|
|
|
|
+ data.content = this.content;
|
|
|
|
+ data.sendid = this.user.uid;
|
|
|
|
+ data.sendname = this.user.name;
|
|
|
|
+ const res = await this.create(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.content = '';
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ channel() {
|
|
|
|
+ console.log('in function:');
|
|
|
|
+ this.$stomp({
|
|
|
|
+ [`/exchange/public_chat_` + this.id]: this.onMessage,
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ onMessage(message) {
|
|
|
|
+ // console.log('receive a message: ', message.body);
|
|
|
|
+ let body = _.get(message, 'body');
|
|
|
|
+ if (body) {
|
|
|
|
+ body = JSON.parse(body);
|
|
|
|
+ this.dataList.push(body);
|
|
|
|
+ this.content = '';
|
|
|
|
+ }
|
|
|
|
+ // const { content, contenttype, sendid, sendname, icon, groupid, sendtime, type } = message.headers;
|
|
|
|
+ // let object = { content, contenttype, sendid, sendname, icon, groupid, sendtime, type };
|
|
|
|
+ // this.list.push(object);
|
|
|
|
+ },
|
|
|
|
+ async getDevices() {
|
|
|
|
+ this.cameras = await TRTC.getCameras();
|
|
|
|
+ this.microphones = await TRTC.getMicrophones();
|
|
|
|
+ },
|
|
|
|
+ async initclient() {
|
|
|
|
+ console.log(this.user.uid);
|
|
|
|
+ this.userId_ = this.user.uid;
|
|
|
|
+ if (this.anchorid === this.user.uid) {
|
|
|
|
+ this.showbtn_ = true;
|
|
|
|
+ this.userMainId_ = 'mainr-' + this.user.uid;
|
|
|
|
+ } else {
|
|
|
|
+ this.userMainId_ = 'other-' + this.user.uid;
|
|
|
|
+ }
|
|
|
|
+ const res = await this.gensignFetch({ userid: this.userMainId_ });
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ console.log(res.data);
|
|
|
|
+ this.client_ = TRTC.createClient({
|
|
|
|
+ mode: 'live',
|
|
|
|
+ sdkAppId: this.sdkAppId_,
|
|
|
|
+ userId: this.userMainId_,
|
|
|
|
+ userSig: res.data,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async liveon() {
|
|
|
|
+ this.open_ = true;
|
|
|
|
+ console.log('8888--' + this.userId_);
|
|
|
|
+ if (this.cameraId === '' || this.microphoneId === '') {
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '请选择摄像头和麦克风',
|
|
|
|
+ type: 'warning',
|
|
|
|
+ });
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ await this.client_.join({ roomId: this.name, role: 'anchor' });
|
|
|
|
+ this.localStream_ = await TRTC.createStream({
|
|
|
|
+ audio: true,
|
|
|
|
+ video: true,
|
|
|
|
+ cameraId: this.cameraId,
|
|
|
|
+ microphoneId: this.microphoneId,
|
|
|
|
+ userId: this.userMainId_,
|
|
|
|
+ });
|
|
|
|
+ this.localStream_.setVideoProfile('480p');
|
|
|
|
+ await this.localStream_.initialize();
|
|
|
|
+ console.log('initialize local stream success');
|
|
|
|
+ // publish the local stream
|
|
|
|
+ await this.client_.publish(this.localStream_);
|
|
|
|
+ this.localStream_.play('main-video');
|
|
|
|
+ //$('#mask_main').appendTo($('#player_' + this.localStream_.getId()));
|
|
|
|
+
|
|
|
|
+ // 订阅其他用户音视频
|
|
|
|
+ this.client_.on('stream-subscribed', event => {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ // 远端流订阅成功,播放远端音视频流
|
|
|
|
+ const usertempid_ = remoteStream.getUserId();
|
|
|
|
+ console.log('111' + remoteStream.getUserId());
|
|
|
|
+ if (usertempid_) {
|
|
|
|
+ const usersplit_ = usertempid_.substring(0, 5);
|
|
|
|
+ if (usersplit_ === 'other') {
|
|
|
|
+ const id_ = 'othe-video-' + usertempid_;
|
|
|
|
+ remoteStream.play(id_);
|
|
|
|
+ } else if (usersplit_ === 'wxxcx') {
|
|
|
|
+ const id_ = 'look-video-' + usertempid_;
|
|
|
|
+ remoteStream.play(id_);
|
|
|
|
+ } else if (usersplit_ === 'meetu') {
|
|
|
|
+ const id_ = 'look-video-' + usertempid_;
|
|
|
|
+ remoteStream.play(id_);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // 监听远端流增加事件
|
|
|
|
+ this.client_.on('stream-added', event => {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ console.log('222' + remoteStream.getType());
|
|
|
|
+ // 订阅远端音频和视频流
|
|
|
|
+ this.client_.subscribe(remoteStream, { audio: true, video: true }).catch(e => {
|
|
|
|
+ console.error('failed to subscribe remoteStream');
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ this.client_.on('stream-removed', event => {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ console.log('stop----');
|
|
|
|
+ const usertempid_ = remoteStream.getUserId();
|
|
|
|
+ if (usertempid_) {
|
|
|
|
+ const usersplit_ = usertempid_.substring(0, 5);
|
|
|
|
+ if (usersplit_ === 'other') {
|
|
|
|
+ this.index_ = this.index_ - 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ remoteStream.stop();
|
|
|
|
+ });
|
|
|
|
+ this.client_.on('mute-video', event => {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ // 订阅远端音频和视频流
|
|
|
|
+ const usertempid_ = remoteStream.getUserId();
|
|
|
|
+ if (usertempid_) {
|
|
|
|
+ const usersplit_ = usertempid_.substring(0, 4);
|
|
|
|
+ if (usersplit_ === 'othe') {
|
|
|
|
+ this.index_ = this.index_ - 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ async shareon() {
|
|
|
|
+ const shareId = 'share-' + this.userId_;
|
|
|
|
+ this.shareid = shareId;
|
|
|
|
+ const res = await this.gensignFetch({ userid: shareId });
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ const shareClient = TRTC.createClient({
|
|
|
|
+ mode: 'videoCall',
|
|
|
|
+ sdkAppId: this.sdkAppId_,
|
|
|
|
+ userId: shareId,
|
|
|
|
+ userSig: res.data,
|
|
|
|
+ });
|
|
|
|
+ this.shareClient_ = shareClient;
|
|
|
|
+ shareClient.setDefaultMuteRemoteStreams(true);
|
|
|
|
+ await shareClient.join({ roomId: this.name });
|
|
|
|
+ const localStream = TRTC.createStream({ audio: false, screen: true });
|
|
|
|
+ //localStream.setScreenProfile({ width: 200, height: 200, float: 'left', frameRate: 5, bitrate: 1600 /* kbps */ });
|
|
|
|
+ await localStream.initialize();
|
|
|
|
+ this.shareStream_ = localStream;
|
|
|
|
+ console.log('initialize share stream success');
|
|
|
|
+ await shareClient.publish(localStream);
|
|
|
|
+ this.client_.on('stream-added', event => {
|
|
|
|
+ const remoteStream = event.stream;
|
|
|
|
+ const remoteUserId = remoteStream.getUserId();
|
|
|
|
+ if (remoteUserId === shareId) {
|
|
|
|
+ // 取消订阅自己的屏幕分享流
|
|
|
|
+ this.client_.unsubscribe(remoteStream);
|
|
|
|
+ } else {
|
|
|
|
+ // 订阅其他一般远端流
|
|
|
|
+ this.client_.subscribe(remoteStream);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async liveclose() {
|
|
|
|
+ // 关闭视频通话
|
|
|
|
+ console.log(this.open_);
|
|
|
|
+ if (this.open_) {
|
|
|
|
+ const videoTrack = this.localStream_.getVideoTrack();
|
|
|
|
+ if (videoTrack) {
|
|
|
|
+ this.localStream_.removeTrack(videoTrack).then(() => {
|
|
|
|
+ console.log('remove video call success');
|
|
|
|
+ // 关闭摄像头
|
|
|
|
+ videoTrack.stop();
|
|
|
|
+ this.client_.unpublish(this.localStream_).then(() => {
|
|
|
|
+ // 取消发布本地流成功
|
|
|
|
+ });
|
|
|
|
+ this.localStream_.close();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async shareclose() {
|
|
|
|
+ this.shareClient_;
|
|
|
|
+ if (this.shareClient_) {
|
|
|
|
+ this.shareClient_.unpublish(this.shareStream_).then(() => {
|
|
|
|
+ // 关闭屏幕分享流
|
|
|
|
+ this.shareStream_.close();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ async cameraChange() {
|
|
|
|
+ //await this.localStream_.switchDevice('video', this.cameraId);
|
|
|
|
+ },
|
|
|
|
+ async micrChange() {
|
|
|
|
+ //await this.localStream_.switchDevice('audio', this.microphoneId);
|
|
|
|
+ },
|
|
|
|
+ // 选择打开摄像头
|
|
|
|
+ shexiangBtn() {
|
|
|
|
+ this.shexiangDia = true;
|
|
|
|
+ },
|
|
|
|
+ // 选择打开麦克风
|
|
|
|
+ tianchongBtn() {
|
|
|
|
+ this.tianchongDia = true;
|
|
|
|
+ },
|
|
|
|
+ chatBtn() {
|
|
|
|
+ this.chatDia = true;
|
|
|
|
+ },
|
|
|
|
+ async queBtn() {
|
|
|
|
+ this.queDia = true;
|
|
|
|
+ this.questSearch();
|
|
|
|
+ },
|
|
|
|
+ async queCloseBtn() {
|
|
|
|
+ // 关闭问卷
|
|
|
|
+ const data = {};
|
|
|
|
+ data.roomid = this.id;
|
|
|
|
+ const res = await this.roomquestclose(data);
|
|
|
|
+ if (this.$checkRes(res)) {
|
|
|
|
+ this.$message({
|
|
|
|
+ message: '操作成功',
|
|
|
|
+ type: 'success',
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ forId(itemid) {
|
|
|
|
+ return 'look-video-wxxcx-' + itemid;
|
|
|
|
+ },
|
|
|
|
+ forOtherId(itemid) {
|
|
|
|
+ return 'othe-video-other-' + itemid;
|
|
|
|
+ },
|
|
|
|
+ // 关闭摄像头&麦克风
|
|
|
|
+ handleClose(done) {
|
|
|
|
+ done();
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ ...mapState(['user']),
|
|
|
|
+ id() {
|
|
|
|
+ return this.$route.query.id;
|
|
|
|
+ },
|
|
|
|
+ name() {
|
|
|
|
+ return this.$route.query.name;
|
|
|
|
+ },
|
|
|
|
+ anchorid() {
|
|
|
|
+ return this.$route.query.anchorid;
|
|
|
|
+ },
|
|
|
|
+ pageTitle() {
|
|
|
|
+ return `${this.$route.meta.title}`;
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ metaInfo() {
|
|
|
|
+ return { title: this.$route.meta.title };
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
+.info {
|
|
|
|
+ background-color: #2a2b30;
|
|
|
|
+ min-height: 840px;
|
|
|
|
+ .left {
|
|
|
|
+ .leftTop {
|
|
|
|
+ min-height: 540px;
|
|
|
|
+ padding: 0 15px;
|
|
|
|
+ margin: 20px 0;
|
|
|
|
+ p {
|
|
|
|
+ color: #ccc;
|
|
|
|
+ }
|
|
|
|
+ p:nth-child(2) {
|
|
|
|
+ padding: 10px 0;
|
|
|
|
+ }
|
|
|
|
+ p:nth-child(3) {
|
|
|
|
+ line-height: 25px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .leftDown {
|
|
|
|
+ padding: 10px 0 0 0;
|
|
|
|
+ border-top: 1px solid #000;
|
|
|
|
+ .btn {
|
|
|
|
+ margin: 0 0 15px 0;
|
|
|
|
+ color: #cccccc;
|
|
|
|
+ text-align: center;
|
|
|
|
+ }
|
|
|
|
+ .btn:hover {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .right {
|
|
|
|
+ .rightTop {
|
|
|
|
+ height: 100px;
|
|
|
|
+ background-color: #232428;
|
|
|
|
+ text-align: right;
|
|
|
|
+ color: #ccc;
|
|
|
|
+ line-height: 100px;
|
|
|
|
+ span {
|
|
|
|
+ margin: 0 10px 0 0;
|
|
|
|
+ }
|
|
|
|
+ span:hover {
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ color: #409eff;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .video {
|
|
|
|
+ min-height: 640px;
|
|
|
|
+ background-color: #000;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ position: relative;
|
|
|
|
+ .videoMeet {
|
|
|
|
+ .one {
|
|
|
|
+ height: 480px;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+ .two {
|
|
|
|
+ height: 480px;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ background-color: white;
|
|
|
|
+ .twoOne {
|
|
|
|
+ height: 80px;
|
|
|
|
+ width: 100%;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ span:first-child {
|
|
|
|
+ width: 100%;
|
|
|
|
+ text-align: center;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
+ white-space: nowrap;
|
|
|
|
+ // font-weight: bold;
|
|
|
|
+ }
|
|
|
|
+ span:last-child {
|
|
|
|
+ width: 100%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .three {
|
|
|
|
+ height: 160px;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .noVideo {
|
|
|
|
+ min-height: 640px;
|
|
|
|
+ background-color: #151618;
|
|
|
|
+ }
|
|
|
|
+ .rightDown {
|
|
|
|
+ height: 100px;
|
|
|
|
+ background-color: #232428;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+/deep/.el-dialog__body {
|
|
|
|
+ min-height: 100px;
|
|
|
|
+}
|
|
|
|
+#main-video {
|
|
|
|
+ float: left;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 640px;
|
|
|
|
+ min-height: 600px;
|
|
|
|
+ grid-area: 1/1/3/4;
|
|
|
|
+}
|
|
|
|
+.chatList {
|
|
|
|
+ height: 400px;
|
|
|
|
+ padding: 5px 5px 5px 0px;
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+ .list {
|
|
|
|
+ margin: 0 0 10px 0;
|
|
|
|
+ span:first-child {
|
|
|
|
+ float: left;
|
|
|
|
+ width: 15%;
|
|
|
|
+ text-align: center;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
+ white-space: nowrap;
|
|
|
|
+ // font-weight: bold;
|
|
|
|
+ }
|
|
|
|
+ span:last-child {
|
|
|
|
+ float: right;
|
|
|
|
+ width: 84%;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+.chatInput {
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ .el-button {
|
|
|
|
+ width: 100%;
|
|
|
|
+ padding: 20px 0;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+.sudoku_row {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 430px;
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
+ overflow-y: auto;
|
|
|
|
+}
|
|
|
|
+.sudoku_item {
|
|
|
|
+ display: flex;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ align-items: center;
|
|
|
|
+ flex-direction: column;
|
|
|
|
+ width: 30%;
|
|
|
|
+ padding: 10px 10px 10px 10px;
|
|
|
|
+}
|
|
|
|
+.lookvideo {
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 160px;
|
|
|
|
+ min-height: 160px;
|
|
|
|
+ background-color: black;
|
|
|
|
+ grid-area: 1/1/3/4;
|
|
|
|
+}
|
|
|
|
+.othevideo {
|
|
|
|
+ margin: 10px 10px 10px 10px;
|
|
|
|
+ width: 80px;
|
|
|
|
+ height: 80px;
|
|
|
|
+ min-height: 80px;
|
|
|
|
+ background-color: black;
|
|
|
|
+ grid-area: 1/1/3/4;
|
|
|
|
+}
|
|
|
|
+</style>
|