detailInfo.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. <template>
  2. <div id="detailInfo">
  3. <el-row>
  4. <el-col :span="24" class="info">
  5. <el-col :span="4" class="left">
  6. <el-col :span="24" class="leftTop">
  7. <el-image :src="roomdetail.filedir"></el-image>
  8. <p>{{ roomdetail.title }}</p>
  9. <p>{{ roomdetail.content }}</p>
  10. </el-col>
  11. <el-col :span="24" class="leftDown">
  12. <el-col :span="8" class="btn" @click.native="shexiangBtn()">
  13. <i class="iconfont iconshexiangtou"></i>
  14. <p>摄像头</p>
  15. </el-col>
  16. <el-col :span="8" class="btn" @click.native="tianchongBtn()">
  17. <i class="iconfont iconmaikefeng-tianchong"></i>
  18. <p>麦克风</p>
  19. </el-col>
  20. <el-col :span="8" class="btn" @click.native="chatBtn()">
  21. <i class="el-icon-user"></i>
  22. <p>聊天</p>
  23. </el-col>
  24. </el-col>
  25. <el-col :span="24" class="leftDown">
  26. <el-col :span="8" class="btn" @click.native="lookuserBtn()">
  27. <i class="el-icon-user"></i>
  28. <p>成员</p>
  29. </el-col>
  30. <el-col :span="8" class="btn" @click.native="queBtn()">
  31. <i class="el-icon-question"></i>
  32. <p>问卷</p>
  33. </el-col>
  34. <el-col :span="8" class="btn" @click.native="queCloseBtn()">
  35. <i class="el-icon-circle-close"></i>
  36. <p>停卷</p>
  37. </el-col>
  38. </el-col>
  39. </el-col>
  40. <el-col :span="20" class="right">
  41. <el-col :span="24" class="rightTop">
  42. <span @click="liveon"><i class="iconfont iconshexiangtou"></i>直播</span>
  43. <span @click="liveclose"><i class="el-icon-switch-button"></i>关闭</span>
  44. <span @click="shareon"><i class="iconfont iconfenxiang"></i>屏幕</span>
  45. <span><el-switch @change="recordclick" v-model="isrecord" active-text="录制" inactive-text="停录"> </el-switch></span>
  46. </el-col>
  47. <el-col :span="2" class="noVideo"> </el-col>
  48. <el-col :span="20" class="video">
  49. <el-col :span="24" class="videoMeet">
  50. <el-col :span="18" class="one">
  51. <div id="main-video" class="video-box col-div" style="justify-content: flex-end"></div>
  52. </el-col>
  53. <el-col :span="6" class="two">
  54. <el-col v-show="zjrshow" :span="24" class="twoOne" v-for="(item, index) in zjrList" :key="index">
  55. <p>
  56. <span class="zjr-sel-info">{{ item.zjrname }}</span>
  57. <span class="twobtn">
  58. <el-button type="danger" size="mini" @click="zjrChange(item.zjrid)">主讲</el-button>
  59. </span>
  60. </p>
  61. </el-col>
  62. </el-col>
  63. </el-col>
  64. </el-col>
  65. <el-col :span="2" class="noVideo"></el-col>
  66. <el-col :span="24" class="rightDown">
  67. <!-- 开始直播 -->
  68. </el-col>
  69. </el-col>
  70. </el-col>
  71. </el-row>
  72. <el-dialog title="摄像头" :visible.sync="shexiangDia" width="30%" :before-close="handleClose">
  73. <el-select @change="cameraChange" v-model="cameraId" filterable placeholder="请选择摄像头">
  74. <el-option v-for="item in cameras" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
  75. </el-select>
  76. </el-dialog>
  77. <el-dialog title="麦克风" :visible.sync="tianchongDia" width="30%" :before-close="handleClose">
  78. <el-select @change="micrChange" v-model="microphoneId" filterable placeholder="请选择麦克风">
  79. <el-option v-for="item in microphones" :key="item.deviceId" :label="item.label" :value="item.deviceId"> </el-option>
  80. </el-select>
  81. </el-dialog>
  82. <el-dialog title="讨论" :visible.sync="chatDia" width="50%" :before-close="handleClose">
  83. <el-row>
  84. <el-col :span="24" class="chatList">
  85. <el-col :span="24" class="list" v-for="(item, index) in dataList" :key="index">
  86. <p>
  87. <span :class="item.sendname == user.name ? 'selfColor' : ''">{{ item.sendname }}</span>
  88. <span>{{ item.content }}</span>
  89. </p>
  90. </el-col>
  91. </el-col>
  92. <el-col :span="24" class="chatInput">
  93. <el-col :span="19" class="input">
  94. <el-input type="textarea" maxlength="5000" show-word-limit v-model="content"></el-input>
  95. </el-col>
  96. <el-col :span="5" class="btn">
  97. <el-button type="primary" size="mini" @click="chatCreate">发送</el-button>
  98. </el-col>
  99. </el-col>
  100. </el-row>
  101. </el-dialog>
  102. <el-dialog title="问卷" :visible.sync="queDia" width="38%" :before-close="handleClose">
  103. <el-row>
  104. <el-col :span="24">
  105. <el-col :span="12">
  106. <el-select v-model="queid" filterable placeholder="请选择问卷">
  107. <el-option v-for="item in questList" :key="item.id" :label="item.name" :value="item.id"> </el-option>
  108. </el-select>
  109. </el-col>
  110. <el-col :span="12" class="btn">
  111. <el-button type="primary" size="mini" @click="queCreate">发送</el-button>
  112. </el-col>
  113. </el-col>
  114. </el-row>
  115. </el-dialog>
  116. <el-dialog title="成员" :visible.sync="lookuserDia" width="60%" height="450px" :before-close="handleClose" :close-on-click-modal="(clo = false)">
  117. <el-row>
  118. <el-col :span="24" class="sudoku_row">
  119. <el-col :span="24" class="sudoku_item" v-for="(item, index) in userList" :key="index">
  120. <div :id="forId(item.userid)" class="video-box col-div lookvideo" style="justify-content: flex-end"></div>
  121. <p>
  122. <i class="el-icon-user"></i>
  123. <span class="selfColor">{{ item.username }}</span>
  124. <span v-if="item.switchrole === 'anchor'">
  125. <el-button type="danger" size="mini" @click="lookuserUpdate(item.id, 'audience')">移除</el-button>
  126. <el-button type="primary" size="mini" @click="roomshangmai(item.userid)">主讲</el-button>
  127. </span>
  128. <span v-else><el-button type="primary" size="mini" @click="lookuserUpdate(item.id, 'anchor')">连麦</el-button></span>
  129. </p>
  130. </el-col>
  131. </el-col>
  132. </el-row>
  133. </el-dialog>
  134. </div>
  135. </template>
  136. <script>
  137. import Vue from 'vue';
  138. import { mapState, createNamespacedHelpers } from 'vuex';
  139. const { mapActions: gensign } = createNamespacedHelpers('gensign');
  140. const { mapActions: chat } = createNamespacedHelpers('chat');
  141. const { mapActions: room } = createNamespacedHelpers('room');
  142. const { mapActions: lookuser } = createNamespacedHelpers('lookuser');
  143. const { mapActions: roomuser } = createNamespacedHelpers('roomuser');
  144. import TRTC from 'trtc-js-sdk';
  145. export default {
  146. name: 'detailInfo',
  147. props: {
  148. roomInfo: null,
  149. },
  150. components: {},
  151. data: function() {
  152. return {
  153. // 摄像头
  154. shexiangDia: false,
  155. cameraId: '',
  156. cameras: [],
  157. // 麦克风
  158. tianchongDia: false,
  159. chatDia: false,
  160. queDia: false,
  161. questList: [],
  162. queid: '',
  163. microphoneId: '',
  164. microphones: [],
  165. client_: '',
  166. localStream_: '',
  167. sdkAppId_: '1400380125',
  168. userId_: '',
  169. userMainId_: '',
  170. open_: false,
  171. content: '',
  172. dataList: [],
  173. isrecord: false,
  174. shareid: '',
  175. userList: [],
  176. lookuserDia: false,
  177. index_: 0,
  178. ov1: '',
  179. ov2: '',
  180. ov3: '',
  181. ov4: '',
  182. ov5: '',
  183. ov6: '',
  184. ov7: '',
  185. showbtn_: false,
  186. roomdetail: {},
  187. zjrList: [],
  188. zjrshow: false,
  189. };
  190. },
  191. created() {
  192. this.getRoomInfo();
  193. this.initclient();
  194. this.getDevices();
  195. this.chatSearch();
  196. },
  197. mounted() {
  198. this.channel();
  199. },
  200. methods: {
  201. ...gensign(['gensignFetch']),
  202. ...chat(['query', 'create', 'fetch']),
  203. ...room({
  204. roomfetch: 'fetch',
  205. startrecord: 'startrecord',
  206. stoprecord: 'stoprecord',
  207. roomquest: 'roomquest',
  208. roomquestclose: 'roomquestclose',
  209. questquery: 'questquery',
  210. updateanchor: 'updateanchor',
  211. updateshmai: 'updateshmai',
  212. switchzjr: 'switchzjr',
  213. }),
  214. ...lookuser(['lookquery', 'lookupdate']),
  215. ...roomuser({ roomuserfetch: 'fetch' }),
  216. async zjrChange(zjrid) {
  217. const data = {};
  218. data.id = this.id;
  219. data.switchzjr = zjrid;
  220. const res = await this.switchzjr(data);
  221. if (this.$checkRes(res)) {
  222. console.log(res.data);
  223. this.$message({
  224. message: '操作成功',
  225. type: 'success',
  226. });
  227. }
  228. },
  229. async getRoomInfo() {
  230. const res = await this.roomfetch(this.id);
  231. if (this.$checkRes(res)) {
  232. console.log(res.data);
  233. this.$set(this, `roomdetail`, res.data);
  234. if (res.data.anchorid === this.user.uid) {
  235. this.zjrshow = true;
  236. }
  237. for (const elm of res.data.zjr) {
  238. const ru = await this.roomuserfetch(elm);
  239. if (this.$checkRes(ru)) {
  240. const newdata = { zjrid: elm, zjrname: ru.data.name };
  241. this.zjrList.push(newdata);
  242. }
  243. }
  244. }
  245. },
  246. async roomshangmai(dataid) {
  247. const data = {};
  248. data.id = this.id;
  249. data.shmaiid = dataid;
  250. const res = await this.updateshmai(data);
  251. if (this.$checkRes(res)) {
  252. console.log(res.data);
  253. this.$message({
  254. message: '操作成功',
  255. type: 'success',
  256. });
  257. }
  258. },
  259. async queCreate() {
  260. const data = {};
  261. data.roomid = this.id;
  262. data.queid = this.queid;
  263. const res = await this.roomquest(data);
  264. if (this.$checkRes(res)) {
  265. console.log(res.data);
  266. this.$message({
  267. message: '操作成功',
  268. type: 'success',
  269. });
  270. }
  271. },
  272. async lookuserBtn() {
  273. this.lookuserDia = true;
  274. this.lookuserSearch();
  275. },
  276. async lookuserSearch({ skip = 0, limit = 1000 } = {}) {
  277. const info = { roomid: this.id };
  278. let res = await this.lookquery({ skip, limit, ...info });
  279. console.log(res.data);
  280. this.$set(this, `userList`, res.data);
  281. },
  282. async lookuserUpdate(_id, _switchrole) {
  283. console.log(_id);
  284. let data = {};
  285. data.id = _id;
  286. data.switchrole = _switchrole;
  287. const res = await this.lookupdate(data);
  288. if (this.$checkRes(res)) {
  289. console.log(res.data);
  290. this.$message({
  291. message: '操作成功',
  292. type: 'success',
  293. });
  294. this.lookuserSearch();
  295. } else {
  296. this.$message.error(res.errmsg);
  297. }
  298. },
  299. async recordclick() {
  300. console.log(this.isrecord);
  301. if (this.isrecord) {
  302. const info = { roomid: this.id, roomname: this.name, shareid: this.shareid };
  303. let res = await this.startrecord({ ...info });
  304. } else {
  305. const info = { roomid: this.id, roomname: this.name };
  306. let res = await this.stoprecord({ ...info });
  307. }
  308. },
  309. async chatSearch({ skip = 0, limit = 1000 } = {}) {
  310. const info = { roomid: this.id };
  311. let res = await this.query({ skip, limit, ...info });
  312. this.$set(this, `dataList`, res.data);
  313. },
  314. async questSearch({ skip = 0, limit = 1000 } = {}) {
  315. const info = { status: '1' };
  316. let res = await this.questquery({ skip, limit, ...info });
  317. console.log(res);
  318. if (this.$checkRes(res)) {
  319. this.$set(this, `questList`, res.data);
  320. }
  321. },
  322. async chatCreate() {
  323. let data = {};
  324. data.roomid = this.id;
  325. data.type = '0';
  326. data.content = this.content;
  327. data.sendid = this.user.uid;
  328. data.sendname = this.user.name;
  329. const res = await this.create(data);
  330. if (this.$checkRes(res)) {
  331. console.log(res.data);
  332. this.content = '';
  333. }
  334. },
  335. channel() {
  336. console.log('in function:');
  337. this.$stomp({
  338. [`/exchange/public_chat_` + this.id]: this.onMessage,
  339. });
  340. },
  341. onMessage(message) {
  342. // console.log('receive a message: ', message.body);
  343. let body = _.get(message, 'body');
  344. if (body) {
  345. body = JSON.parse(body);
  346. this.dataList.push(body);
  347. this.content = '';
  348. }
  349. // const { content, contenttype, sendid, sendname, icon, groupid, sendtime, type } = message.headers;
  350. // let object = { content, contenttype, sendid, sendname, icon, groupid, sendtime, type };
  351. // this.list.push(object);
  352. },
  353. async getDevices() {
  354. this.cameras = await TRTC.getCameras();
  355. this.microphones = await TRTC.getMicrophones();
  356. },
  357. async initclient() {
  358. console.log(this.user.uid);
  359. this.userId_ = this.user.uid;
  360. if (this.anchorid === this.user.uid) {
  361. this.showbtn_ = true;
  362. this.userMainId_ = 'mainr-' + this.user.uid;
  363. } else {
  364. this.userMainId_ = 'other-' + this.user.uid;
  365. }
  366. const res = await this.gensignFetch({ userid: this.userMainId_ });
  367. if (this.$checkRes(res)) {
  368. console.log(res.data);
  369. this.client_ = TRTC.createClient({
  370. mode: 'live',
  371. sdkAppId: this.sdkAppId_,
  372. userId: this.userMainId_,
  373. userSig: res.data,
  374. });
  375. }
  376. },
  377. async liveon() {
  378. this.open_ = true;
  379. console.log('8888--' + this.userId_);
  380. if (this.cameraId === '' || this.microphoneId === '') {
  381. this.$message({
  382. message: '请选择摄像头和麦克风',
  383. type: 'warning',
  384. });
  385. return;
  386. }
  387. await this.client_.join({ roomId: this.name, role: 'anchor' });
  388. this.localStream_ = await TRTC.createStream({
  389. audio: true,
  390. video: true,
  391. cameraId: this.cameraId,
  392. microphoneId: this.microphoneId,
  393. userId: this.userMainId_,
  394. });
  395. this.localStream_.setVideoProfile('480p');
  396. await this.localStream_.initialize();
  397. console.log('initialize local stream success');
  398. // publish the local stream
  399. await this.client_.publish(this.localStream_);
  400. this.localStream_.play('main-video');
  401. //$('#mask_main').appendTo($('#player_' + this.localStream_.getId()));
  402. // 订阅其他用户音视频
  403. this.client_.on('stream-subscribed', event => {
  404. const remoteStream = event.stream;
  405. // 远端流订阅成功,播放远端音视频流
  406. const usertempid_ = remoteStream.getUserId();
  407. console.log('111' + remoteStream.getUserId());
  408. if (usertempid_) {
  409. const usersplit_ = usertempid_.substring(0, 5);
  410. if (usersplit_ === 'other') {
  411. this.index_ = this.index_ + 1;
  412. const id_ = 'othe-video-' + this.index_;
  413. const ovid = usertempid_.substring(6);
  414. if (this.index_ === 1) {
  415. this.ov1 = ovid;
  416. } else if (this.index_ === 2) {
  417. this.ov2 = ovid;
  418. } else if (this.index_ === 3) {
  419. this.ov3 = ovid;
  420. } else if (this.index_ === 4) {
  421. this.ov4 = ovid;
  422. } else if (this.index_ === 5) {
  423. this.ov5 = ovid;
  424. } else if (this.index_ === 6) {
  425. this.ov6 = ovid;
  426. } else if (this.index_ === 7) {
  427. this.ov7 = ovid;
  428. }
  429. this.ov1 = '';
  430. remoteStream.play(id_);
  431. } else if (usersplit_ === 'wxxcx') {
  432. const id_ = 'look-video-' + usertempid_;
  433. remoteStream.play(id_);
  434. } else if (usersplit_ === 'meetu') {
  435. const ovid = usertempid_.substring(6);
  436. const id_ = 'look-video-' + ovid;
  437. remoteStream.play(id_);
  438. }
  439. }
  440. });
  441. // 监听远端流增加事件
  442. this.client_.on('stream-added', event => {
  443. const remoteStream = event.stream;
  444. console.log('222' + remoteStream.getType());
  445. // 订阅远端音频和视频流
  446. this.client_.subscribe(remoteStream, { audio: true, video: true }).catch(e => {
  447. console.error('failed to subscribe remoteStream');
  448. });
  449. });
  450. this.client_.on('stream-removed', event => {
  451. const remoteStream = event.stream;
  452. console.log('stop----');
  453. const usertempid_ = remoteStream.getUserId();
  454. if (usertempid_) {
  455. const usersplit_ = usertempid_.substring(0, 5);
  456. if (usersplit_ === 'other') {
  457. this.index_ = this.index_ - 1;
  458. }
  459. }
  460. remoteStream.stop();
  461. });
  462. this.client_.on('mute-video', event => {
  463. const remoteStream = event.stream;
  464. // 订阅远端音频和视频流
  465. const usertempid_ = remoteStream.getUserId();
  466. if (usertempid_) {
  467. const usersplit_ = usertempid_.substring(0, 4);
  468. if (usersplit_ === 'othe') {
  469. this.index_ = this.index_ - 1;
  470. }
  471. }
  472. });
  473. },
  474. async shareon() {
  475. const shareId = 'share-' + this.userId_;
  476. this.shareid = shareId;
  477. const res = await this.gensignFetch({ userid: shareId });
  478. if (this.$checkRes(res)) {
  479. const shareClient = TRTC.createClient({
  480. mode: 'videoCall',
  481. sdkAppId: this.sdkAppId_,
  482. userId: shareId,
  483. userSig: res.data,
  484. });
  485. shareClient.setDefaultMuteRemoteStreams(true);
  486. await shareClient.join({ roomId: this.name });
  487. const localStream = TRTC.createStream({ audio: false, screen: true });
  488. //localStream.setScreenProfile({ width: 200, height: 200, float: 'left', frameRate: 5, bitrate: 1600 /* kbps */ });
  489. await localStream.initialize();
  490. console.log('initialize share stream success');
  491. await shareClient.publish(localStream);
  492. this.client_.on('stream-added', event => {
  493. const remoteStream = event.stream;
  494. const remoteUserId = remoteStream.getUserId();
  495. if (remoteUserId === shareId) {
  496. // 取消订阅自己的屏幕分享流
  497. this.client_.unsubscribe(remoteStream);
  498. } else {
  499. // 订阅其他一般远端流
  500. this.client_.subscribe(remoteStream);
  501. }
  502. });
  503. }
  504. },
  505. async liveclose() {
  506. // 关闭视频通话
  507. console.log(this.open_);
  508. if (this.open_) {
  509. const videoTrack = this.localStream_.getVideoTrack();
  510. if (videoTrack) {
  511. this.localStream_.removeTrack(videoTrack).then(() => {
  512. console.log('remove video call success');
  513. // 关闭摄像头
  514. videoTrack.stop();
  515. this.client_.unpublish(this.localStream_).then(() => {
  516. // 取消发布本地流成功
  517. });
  518. });
  519. }
  520. }
  521. },
  522. async roomAnchorid(type) {
  523. const data = {};
  524. data.roomid = this.id;
  525. if (type === 'othe1') {
  526. data.otheid = this.ov1;
  527. } else if (type === 'othe2') {
  528. data.otheid = this.ov2;
  529. } else if (type === 'othe3') {
  530. data.otheid = this.ov3;
  531. } else if (type === 'othe4') {
  532. data.otheid = this.ov4;
  533. } else if (type === 'othe5') {
  534. data.otheid = this.ov5;
  535. } else if (type === 'othe6') {
  536. data.otheid = this.ov6;
  537. } else if (type === 'othe7') {
  538. data.otheid = this.ov7;
  539. }
  540. const res = await this.updateanchor(data);
  541. if (this.$checkRes(res)) {
  542. this.$message({
  543. message: '操作成功',
  544. type: 'success',
  545. });
  546. }
  547. },
  548. async cameraChange() {
  549. //await this.localStream_.switchDevice('video', this.cameraId);
  550. },
  551. async micrChange() {
  552. //await this.localStream_.switchDevice('audio', this.microphoneId);
  553. },
  554. // 选择打开摄像头
  555. shexiangBtn() {
  556. this.shexiangDia = true;
  557. },
  558. // 选择打开麦克风
  559. tianchongBtn() {
  560. this.tianchongDia = true;
  561. },
  562. chatBtn() {
  563. this.chatDia = true;
  564. },
  565. async queBtn() {
  566. this.queDia = true;
  567. this.questSearch();
  568. },
  569. async queCloseBtn() {
  570. // 关闭问卷
  571. const data = {};
  572. data.roomid = this.id;
  573. const res = await this.roomquestclose(data);
  574. if (this.$checkRes(res)) {
  575. this.$message({
  576. message: '操作成功',
  577. type: 'success',
  578. });
  579. }
  580. },
  581. forId(itemid) {
  582. return 'look-video-wxxcx-' + itemid;
  583. },
  584. // 关闭摄像头&麦克风
  585. handleClose(done) {
  586. done();
  587. },
  588. },
  589. computed: {
  590. ...mapState(['user']),
  591. id() {
  592. return this.$route.query.id;
  593. },
  594. name() {
  595. return this.$route.query.name;
  596. },
  597. anchorid() {
  598. return this.$route.query.anchorid;
  599. },
  600. pageTitle() {
  601. return `${this.$route.meta.title}`;
  602. },
  603. },
  604. metaInfo() {
  605. return { title: this.$route.meta.title };
  606. },
  607. };
  608. </script>
  609. <style lang="less" scoped>
  610. .info {
  611. background-color: #2a2b30;
  612. min-height: 840px;
  613. .left {
  614. .leftTop {
  615. min-height: 540px;
  616. padding: 0 15px;
  617. margin: 20px 0;
  618. p {
  619. color: #ccc;
  620. }
  621. p:nth-child(2) {
  622. padding: 10px 0;
  623. }
  624. p:nth-child(3) {
  625. line-height: 25px;
  626. }
  627. }
  628. .leftDown {
  629. padding: 10px 0 0 0;
  630. border-top: 1px solid #000;
  631. .btn {
  632. margin: 0 0 15px 0;
  633. color: #cccccc;
  634. text-align: center;
  635. }
  636. .btn:hover {
  637. cursor: pointer;
  638. }
  639. }
  640. }
  641. .right {
  642. .rightTop {
  643. height: 100px;
  644. background-color: #232428;
  645. text-align: right;
  646. color: #ccc;
  647. line-height: 100px;
  648. span {
  649. margin: 0 10px 0 0;
  650. }
  651. span:hover {
  652. cursor: pointer;
  653. color: #409eff;
  654. }
  655. }
  656. .video {
  657. min-height: 640px;
  658. background-color: #000;
  659. overflow: hidden;
  660. position: relative;
  661. .videoMeet {
  662. .one {
  663. height: 480px;
  664. overflow: hidden;
  665. }
  666. .two {
  667. height: 480px;
  668. overflow: hidden;
  669. background-color: white;
  670. .twoOne {
  671. height: 30px;
  672. width: 100%;
  673. overflow: hidden;
  674. span:first-child {
  675. float: left;
  676. width: 65%;
  677. text-align: left;
  678. overflow: hidden;
  679. text-overflow: ellipsis;
  680. white-space: nowrap;
  681. // font-weight: bold;
  682. }
  683. span:last-child {
  684. float: right;
  685. width: 30%;
  686. }
  687. }
  688. }
  689. .three {
  690. height: 160px;
  691. overflow: hidden;
  692. }
  693. }
  694. }
  695. .noVideo {
  696. min-height: 640px;
  697. background-color: #151618;
  698. }
  699. .rightDown {
  700. height: 100px;
  701. background-color: #232428;
  702. }
  703. }
  704. }
  705. /deep/.el-dialog__body {
  706. min-height: 100px;
  707. }
  708. #main-video {
  709. float: left;
  710. width: 100%;
  711. height: 640px;
  712. min-height: 600px;
  713. grid-area: 1/1/3/4;
  714. }
  715. .chatList {
  716. height: 400px;
  717. padding: 5px 5px 5px 0px;
  718. overflow-y: auto;
  719. .list {
  720. margin: 0 0 10px 0;
  721. span:first-child {
  722. float: left;
  723. width: 15%;
  724. text-align: center;
  725. overflow: hidden;
  726. text-overflow: ellipsis;
  727. white-space: nowrap;
  728. // font-weight: bold;
  729. }
  730. span:last-child {
  731. float: right;
  732. width: 84%;
  733. }
  734. }
  735. }
  736. .chatInput {
  737. position: absolute;
  738. bottom: 0;
  739. .el-button {
  740. width: 100%;
  741. padding: 20px 0;
  742. }
  743. }
  744. .sudoku_row {
  745. display: flex;
  746. align-items: center;
  747. width: 100%;
  748. height: 430px;
  749. flex-wrap: wrap;
  750. overflow-y: auto;
  751. }
  752. .sudoku_item {
  753. display: flex;
  754. justify-content: center;
  755. align-items: center;
  756. flex-direction: column;
  757. width: 30%;
  758. padding: 10px 10px 10px 10px;
  759. }
  760. .lookvideo {
  761. width: 100%;
  762. height: 160px;
  763. min-height: 160px;
  764. background-color: black;
  765. grid-area: 1/1/3/4;
  766. }
  767. </style>