123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- <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="roomInfo.filedir"></el-image>
- <p>{{ roomInfo.title }}</p>
- <p>{{ roomInfo.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>
- <el-col :span="20" class="right">
- <el-col :span="24" class="rightTop">
- <span @click="liveon"><i class="iconfont iconshexiangtou"></i>直播</span>
- <span @click="liveclose">关闭</span>
- <span @click="shareon"><i class="iconfont iconfenxiang"></i>屏幕</span>
- <span><el-switch @change="recordclick" v-model="isrecord" active-text="录制" inactive-text="停录"> </el-switch></span>
- </el-col>
- <el-col :span="2" class="noVideo"> </el-col>
- <el-col :span="20" class="video">
- <div id="main-video" class="video-box col-div" style="justify-content: flex-end"></div>
- </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>
- </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');
- 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,
- microphoneId: '',
- microphones: [],
- client_: '',
- localStream_: '',
- sdkAppId_: '1400380125',
- userId_: '1111',
- open_: false,
- content: '',
- dataList: [],
- isrecord: false,
- };
- },
- created() {
- this.initclient();
- this.getDevices();
- this.chatSearch();
- },
- mounted() {
- this.channel();
- },
- methods: {
- ...gensign(['gensignFetch']),
- ...chat(['query', 'create', 'fetch']),
- ...room(['startrecord', 'stoprecord']),
- async recordclick() {
- console.log(this.isrecord);
- if (this.isrecord) {
- const info = { roomid: this.id, roomname: this.name };
- 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 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;
- const res = await this.gensignFetch({ userid: this.userId_ });
- if (this.$checkRes(res)) {
- console.log(res.data);
- this.client_ = TRTC.createClient({
- mode: 'live',
- sdkAppId: this.sdkAppId_,
- userId: this.userId_,
- 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.userId_,
- });
- 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()));
- },
- async shareon() {
- const shareId = 'share-' + this.userId_;
- 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,
- });
- 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();
- 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(() => {
- // 取消发布本地流成功
- });
- });
- }
- }
- },
- 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;
- },
- // 关闭摄像头&麦克风
- handleClose(done) {
- done();
- },
- },
- computed: {
- ...mapState(['user']),
- id() {
- return this.$route.query.id;
- },
- name() {
- return this.$route.query.name;
- },
- 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;
- }
- .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;
- }
- }
- </style>
|