536 lines
19 KiB
Vue
536 lines
19 KiB
Vue
<template>
|
||
<div class="liveing">
|
||
|
||
<div class="top">
|
||
<div class="left">{{lan.$t('zhiboyemian')}}</div>
|
||
<div class="right">
|
||
<img src="@/static/images/liveshare.png" alt="" @click="fenxiang()" />
|
||
<img src="@/static/images/liveend.png" alt="" @click="visible = true" />
|
||
</div>
|
||
</div>
|
||
<div class="info">
|
||
<LiveingWatcher :list="roominfo.studentlist" @cameta="sendtext" @vol="senvol"></LiveingWatcher>
|
||
<div class="LivePlaying">
|
||
<LivePlaying></LivePlaying>
|
||
<div class="comment">
|
||
<div class="commentitem">
|
||
<span>13:32:30</span>
|
||
<span class="name"> Andy : </span>
|
||
<span> 老师,这个部分可以讲的慢一些吗? </span>
|
||
</div>
|
||
<div class="commentitem">
|
||
<span>13:32:30</span>
|
||
<span class="name"> Andy : </span>
|
||
<span> 老师,这个部分可以讲的慢一些吗? </span>
|
||
</div>
|
||
<div class="commentitem">
|
||
<span>13:32:30</span>
|
||
<span class="name"> Andy : </span>
|
||
<span> 老师,这个部分可以讲的慢一些吗? </span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="others">
|
||
<div :id="'s-' + item.memberid" class="othersitem" v-for="(item, index) in roominfo.studentlist" :key="index">
|
||
<div class="watcher"></div>
|
||
<div class="name">{{item.name}}</div>
|
||
<!-- <img src="" alt="" /> -->
|
||
</div>
|
||
<!-- <div class="othersitem">
|
||
<div class="watcher"></div>
|
||
<div class="name">asdsada</div>
|
||
<img src="" alt="" />
|
||
</div>
|
||
<div class="othersitem">
|
||
<div class="watcher"></div>
|
||
<div class="name">asdsada</div>
|
||
<img src="" alt="" />
|
||
</div>
|
||
<div class="othersitem">
|
||
<div class="watcher"></div>
|
||
<div class="name">asdsada</div>
|
||
<img src="" alt="" />
|
||
</div> -->
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<a-modal v-model:visible="visible" title="Basic Modal" @ok="guanbi">
|
||
<p>{{lan.$t('querenguanbi')}}</p>
|
||
</a-modal>
|
||
</div>
|
||
</template>
|
||
<style lang="scss" scoped>
|
||
.liveing ::v-deep(.ant-breadcrumb) > span:last-child {
|
||
color: #08ae98;
|
||
}
|
||
.liveing {
|
||
width: 1320px;
|
||
height: 563px;
|
||
.top {
|
||
width: 1321px;
|
||
height: 57px;
|
||
background: white;
|
||
border-radius: 18px;
|
||
margin-top: 23px;
|
||
margin-bottom: 29px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
color: #121212;
|
||
font-size: 13px;
|
||
align-items: center;
|
||
.left {
|
||
margin-left: 40px;
|
||
font-weight: bold;
|
||
}
|
||
.right {
|
||
margin-right: 27px;
|
||
> img {
|
||
margin-right: 10px;
|
||
}
|
||
}
|
||
}
|
||
.info {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
.LivePlaying {
|
||
border-radius: 18px;
|
||
margin: 0 35px;
|
||
.comment {
|
||
width: 797px;
|
||
height: 153px;
|
||
background: white;
|
||
border-radius: 18px;
|
||
margin-top: 29px;
|
||
padding: 30px;
|
||
font-size: 12px;
|
||
|
||
color: #121212;
|
||
|
||
.commentitem {
|
||
margin-bottom: 17px;
|
||
.name {
|
||
margin-left: 28px;
|
||
color: #08ae98;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
}
|
||
.liveinfo {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
height: 58px;
|
||
align-items: center;
|
||
.left {
|
||
display: flex;
|
||
color: #121212;
|
||
font-size: 13px;
|
||
margin-left: 29px;
|
||
> div {
|
||
margin-right: 57px;
|
||
}
|
||
.icon {
|
||
width: 25px;
|
||
height: 24px;
|
||
margin-right: 6px;
|
||
}
|
||
}
|
||
.right {
|
||
width: 74px;
|
||
height: 29px;
|
||
border: 1px solid #08ae98;
|
||
border-radius: 3px;
|
||
margin-right: 29px;
|
||
color: #08ae98;
|
||
font-size: 13px;
|
||
line-height: 29px;
|
||
font-weight: bold;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.others {
|
||
width: 252px;
|
||
height: 630px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
.othersitem {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 132px;
|
||
margin-bottom: 35px;
|
||
background-color: #eee;
|
||
border-radius: 18px 18px 0px 0px;
|
||
overflow: hidden;
|
||
.watcher {
|
||
width: 100%;
|
||
height: 29px;
|
||
background: #000000;
|
||
color: white;
|
||
position: absolute;
|
||
opacity: 0.1;
|
||
border-radius: 18px 18px 0px 0px;
|
||
top: 0;
|
||
}
|
||
> img {
|
||
width: 228px;
|
||
height: 132px;
|
||
border-radius: 18px;
|
||
}
|
||
.name {
|
||
position: absolute;
|
||
top: 9px;
|
||
left: 28px;
|
||
font-size: 12px;
|
||
color: #fff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|
||
<script lang="ts">
|
||
import { defineComponent, onMounted, ref, resolveComponent } from "vue";
|
||
import LivePlaying from "@/components/LivePlaying.vue";
|
||
import LiveingWatcher from "@/components/LiveingWatcher.vue";
|
||
import TRTC from "trtc-js-sdk"
|
||
import { getliveinfo, livestop, luzhi, usersig } from '@/api';
|
||
import { useRoute } from 'vue-router';
|
||
import store from '@/store';
|
||
import { message } from 'ant-design-vue';
|
||
import { useI18n } from '@/utils/i18n';
|
||
import TIM from 'tim-js-sdk';
|
||
|
||
export default defineComponent({
|
||
components: {
|
||
LivePlaying,
|
||
LiveingWatcher,
|
||
},
|
||
setup() {
|
||
const lan: any = useI18n();
|
||
console.log(1);
|
||
let client: any;
|
||
let localStream: any;
|
||
let statie = true;
|
||
let userSing = '';
|
||
let type = false;
|
||
const visible = ref(false);
|
||
const roominfo = ref<any>([]);
|
||
console.log(useRoute())
|
||
const id = useRoute().query.id;
|
||
let tim: any;
|
||
TRTC.checkSystemRequirements().then((result: any) => {
|
||
if(!result) {
|
||
message.error(lan.$t('buzhichitonghua'))
|
||
}
|
||
})
|
||
async function qiehuan(){
|
||
// 1 屏幕分享 2 摄像头
|
||
client.unpublish(localStream)
|
||
localStream = type ? TRTC.createStream({ userid: store.state.userinfo.memberid, audio: true, screen: true }) : TRTC.createStream({ userId: 10, audio: false, video: true });
|
||
type = !type;
|
||
localStream.initialize().then(()=>{
|
||
client
|
||
.publish(localStream)
|
||
.catch((error: string) => {
|
||
console.error('本地流发布失败 ' + error);
|
||
})
|
||
.then(() => {
|
||
|
||
localStream.play('local_stream');
|
||
console.log('本地流发布成功');
|
||
});
|
||
});
|
||
|
||
}
|
||
async function shexiang(){
|
||
localStream = TRTC.createStream({ userId: store.state.userinfo.memberid, audio: true, video: true });
|
||
const id = localStream.getId();
|
||
await localStream
|
||
.initialize()
|
||
.catch((error: string) => {
|
||
console.error('初始化本地流失败 ' + error);
|
||
})
|
||
.then(() => {
|
||
console.log('初始化本地流成功');
|
||
client
|
||
.publish(localStream)
|
||
.catch((error: string) => {
|
||
console.error('本地流发布失败 ' + error);
|
||
})
|
||
.then(() => {
|
||
const el = document.querySelector("#local_stream");
|
||
if(el){
|
||
el.innerHTML = ""
|
||
}
|
||
localStream.play('local_stream');
|
||
console.log('本地流发布成功');
|
||
console.log(id, 123)
|
||
});
|
||
});
|
||
}
|
||
|
||
async function pingmu(){
|
||
const result = await TRTC.checkSystemRequirements()
|
||
console.log(result,11111)
|
||
if(!result) {
|
||
message.error(lan.$t('buzhichifenxiang'));
|
||
shexiang()
|
||
return ;
|
||
}
|
||
|
||
localStream = TRTC.createStream({ userid: store.state.userinfo.memberid, audio: true, screen: true });
|
||
const id = localStream.getId();
|
||
await localStream
|
||
.initialize()
|
||
.catch((error: string) => {
|
||
console.error('初始化本地流失败 ' + error);
|
||
message.error(lan.$t('xuanzefenxiangneirong'))
|
||
|
||
setTimeout(()=>{
|
||
pingmu()
|
||
}, 1000)
|
||
})
|
||
.then(() => {
|
||
console.log('初始化本地流成功');
|
||
client
|
||
.publish(localStream)
|
||
.catch((error: string) => {
|
||
console.log('本地流发布失败 ' + error);
|
||
|
||
})
|
||
.then(() => {
|
||
const el = document.querySelector("#local_stream");
|
||
if(el){
|
||
el.innerHTML = ""
|
||
}
|
||
localStream.play('local_stream');
|
||
console.log('本地流发布成功');
|
||
console.log(id , 123)
|
||
});
|
||
});
|
||
}
|
||
|
||
async function init(fun: any, userSig: string): Promise<void>{
|
||
console.log(userSig)
|
||
const el = document.querySelector("#local_stream");
|
||
if(el){
|
||
el.innerHTML = ""
|
||
}
|
||
if (typeof id == "string") {
|
||
roominfo.value = await getliveinfo(parseInt(id))
|
||
console.log(roominfo.value)
|
||
}
|
||
|
||
|
||
client = TRTC.createClient({
|
||
mode: 'rtc',
|
||
sdkAppId: '1400435767',
|
||
userId: store.state.userinfo.memberid,
|
||
userSig: userSig
|
||
});
|
||
client.on('stream-added', (event: { stream: any }) => {
|
||
const remoteStream = event.stream;
|
||
console.log('远端流增加: ' + remoteStream.getId());
|
||
//订阅远端流
|
||
client.subscribe(remoteStream);
|
||
});
|
||
client.on('stream-subscribed', (event: { stream: any }) => {
|
||
const remoteStream = event.stream;
|
||
console.log(remoteStream);
|
||
// 播放远端流
|
||
remoteStream.play('s-' + remoteStream.userId_);
|
||
});
|
||
client
|
||
.join({ roomId: roominfo.value.roomid})
|
||
.catch((error: string) => {
|
||
console.error('进房失败 ' + error);
|
||
})
|
||
.then(() => {
|
||
console.log('进房成功');
|
||
// if(typeof id == "string"){
|
||
luzhi(roominfo.value.roomid)
|
||
// }
|
||
fun()
|
||
});
|
||
|
||
// im 初始化
|
||
tim = TIM.create({
|
||
SDKAppID: 1400400340
|
||
}); // SDK 实例通常用 tim 表示
|
||
tim.setLogLevel(0);
|
||
tim.on(TIM.EVENT.MESSAGE_RECEIVED, function(event: any) {
|
||
// 收到推送的单聊、群聊、群提示、群系统通知的新消息,可通过遍历 event.data 获取消息列表数据并渲染到页面
|
||
// event.name - TIM.EVENT.MESSAGE_RECEIVED
|
||
// event.data - 存储 Message 对象的数组 - [Message]
|
||
for(const i in event.data){
|
||
console.log(event.data[i])
|
||
}
|
||
});
|
||
tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function(event: any) {
|
||
// 收到群组列表更新通知,可通过遍历 event.data 获取群组列表数据并渲染到页面
|
||
// event.name - TIM.EVENT.GROUP_LIST_UPDATED
|
||
// event.data - 存储 Group 对象的数组 - [Group]
|
||
console.log(event.data)
|
||
});
|
||
tim.login({userID: store.state.userinfo.memberid.toString(), userSig: userSig}).then((res: any)=>{
|
||
console.log(res.data); // 登录成功
|
||
if (res.data.repeatLogin === true) {
|
||
// 标识账号已登录,本次登录操作为重复登录。v2.5.1 起支持
|
||
console.log(res.data.errorInfo);
|
||
}
|
||
|
||
}).catch(function(imError: any) {
|
||
console.warn('login error:', imError); // 登录失败的相关信息
|
||
});
|
||
tim.on(TIM.EVENT.SDK_READY, function (){
|
||
const promise = tim.createGroup({
|
||
type: TIM.TYPES.GRP_AVCHATROOM,
|
||
name: 'live',
|
||
groupID: roominfo.value.roomid
|
||
});
|
||
promise.then(function(imResponse: any) { // 创建成功
|
||
console.log(imResponse.data.group); // 创建的群的资料
|
||
tim.joinGroup({
|
||
groupID: roominfo.value.roomid,
|
||
type: TIM.TYPES.GRP_AVCHATROOM
|
||
}).then((res: any)=>{
|
||
switch (res.data.status) {
|
||
case TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL: // 等待管理员同意
|
||
break;
|
||
case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
|
||
console.log(res.data.group); // 加入的群组资料
|
||
break;
|
||
case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}).catch((err: any)=>{
|
||
console.log(err)
|
||
})
|
||
}).catch(function(imError: any) {
|
||
console.warn('createGroup error:', imError); // 创建群组失败的相关信息
|
||
tim.joinGroup({
|
||
groupID: roominfo.value.roomid,
|
||
type: TIM.TYPES.GRP_AVCHATROOM
|
||
}).then((res: any)=>{
|
||
switch (res.data.status) {
|
||
case TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL: // 等待管理员同意
|
||
break;
|
||
case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
|
||
console.log(res.data.group); // 加入的群组资料
|
||
break;
|
||
case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}).catch((err: any)=>{
|
||
console.log(err)
|
||
})
|
||
});
|
||
|
||
});
|
||
|
||
|
||
}
|
||
async function fenxiang(){
|
||
console.log(localStream)
|
||
|
||
|
||
await client.unpublish(localStream).then(() => {
|
||
// 关闭屏幕分享流
|
||
console.log("关闭")
|
||
// client.leave().then(() => {
|
||
// // leaving room success
|
||
// console.log("关闭成功")
|
||
// }).catch((error: string) => {
|
||
// console.error('leaving room failed: ' + error);
|
||
// });
|
||
const el = document.querySelector("#local_stream");
|
||
if(el){
|
||
el.innerHTML = ""
|
||
}
|
||
});
|
||
statie ? await shexiang() : await pingmu();
|
||
statie = !statie;
|
||
console.log(localStream.getId())
|
||
}
|
||
|
||
function guanbi(){
|
||
client.leave().then(() => {
|
||
// leaving room success
|
||
visible.value = false;
|
||
if(typeof id == "string"){
|
||
livestop(id, roominfo.value.roomid)
|
||
}
|
||
}).catch((error: string) => {
|
||
message.error(lan.$t('guanbishibai')+':' + error);
|
||
});
|
||
}
|
||
|
||
function sendtext(id: number){
|
||
const m = tim.createTextMessage({
|
||
to: roominfo.value.roomid,
|
||
conversationType: TIM.TYPES.CONV_GROUP,
|
||
payload: {
|
||
text: `beelinkMuteUserId:${id},isClose:0`
|
||
}
|
||
});
|
||
const promise = tim.sendMessage(m);
|
||
promise.then(function(imResponse: any) {
|
||
// 发送成功
|
||
console.log(imResponse);
|
||
message.success("发送命令成功")
|
||
}).catch(function(imError: any) {
|
||
// 发送失败
|
||
message.error("发送命令失败")
|
||
console.warn('sendMessage error:', imError);
|
||
});
|
||
}
|
||
function sendvol(id: number){
|
||
const m = tim.createTextMessage({
|
||
to: roominfo.value.roomid,
|
||
conversationType: TIM.TYPES.CONV_GROUP,
|
||
payload: {
|
||
text: `beelinkTurnOffTheCameraUserId:${id},isClose:1
|
||
0`
|
||
}
|
||
});
|
||
const promise = tim.sendMessage(m);
|
||
promise.then(function(imResponse: any) {
|
||
// 发送成功
|
||
console.log(imResponse);
|
||
message.success("发送命令成功")
|
||
}).catch(function(imError: any) {
|
||
// 发送失败
|
||
message.error("发送命令失败")
|
||
console.warn('sendMessage error:', imError);
|
||
});
|
||
}
|
||
|
||
onMounted(async ()=>{
|
||
const si = setInterval(async ()=>{
|
||
if(store.state.userinfo.memberid != 0 && store.state.userinfo.memberid){
|
||
clearInterval(si);
|
||
userSing = await usersig(store.state.userinfo.memberid);
|
||
init(pingmu, userSing);
|
||
|
||
}
|
||
})
|
||
|
||
})
|
||
|
||
return{
|
||
fenxiang,
|
||
qiehuan,
|
||
roominfo,
|
||
guanbi,
|
||
visible,
|
||
lan,
|
||
sendtext
|
||
}
|
||
},
|
||
});
|
||
</script> |