feat: 新增直播功能及相关组件
实现以下功能: 1. 在首页展示直播信息,支持点击进入直播间。 2. 添加获取直播流的API调用,动态更新直播数据。 3. 优化直播视图组件,调整样式以提升用户体验。 4. 代码格式化和注释优化,提升可读性。
This commit is contained in:
parent
d24052d24b
commit
0d5a7d6d5d
@ -23,6 +23,7 @@
|
||||
"exif-js": "^2.3.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"mint-ui": "^2.2.13",
|
||||
"qnweb-rtc": "^4.3.1",
|
||||
"qrcodejs2": "^0.0.2",
|
||||
"regenerator-runtime": "^0.14.1",
|
||||
"simple-peer": "^9.11.1",
|
||||
|
@ -11,6 +11,15 @@
|
||||
<img src="../../static/lead/8.png" class="img8" v-if="step == 8"/>
|
||||
<img src="../../static/lead/9.png" class="img9" v-if="step == 9"/>
|
||||
</div> -->
|
||||
<div class="cover" v-if="haveLive">
|
||||
<div class="live_box" v-for="live in liveData" @click="goLive(live.room)">
|
||||
<div>{{ live.title }}</div>
|
||||
<br />
|
||||
<div class="stream_info">
|
||||
<p>開始時間:{{ live.start_time }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<common-top></common-top>
|
||||
<div class="all">
|
||||
<div class="top">
|
||||
@ -47,8 +56,8 @@
|
||||
<p class="kechenginfoR_bt">{{ item.name }}</p>
|
||||
<p class="kechenginfoR_xbt">{{ item.description }}</p>
|
||||
<div class="kechenginfoR_bot">
|
||||
<div class="kechenginfoR_botL"><img src="../../static/img/yanjing.png" alt=""
|
||||
class="yanjing">{{ item.page_view }}人</div>
|
||||
<div class="kechenginfoR_botL"><img src="../../static/img/yanjing.png" alt="" class="yanjing">{{
|
||||
item.page_view }}人</div>
|
||||
<div class="kechenginfoR_botR" @click="goCourseDetail(item.id)">进入课程</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -72,7 +81,9 @@ export default {
|
||||
return {
|
||||
company: {},
|
||||
course: [],
|
||||
step: 0
|
||||
step: 0,
|
||||
haveLive: false,
|
||||
liveData: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -80,6 +91,7 @@ export default {
|
||||
mounted() {
|
||||
|
||||
this.getPageData();
|
||||
this.getLiveStreams();
|
||||
},
|
||||
methods: {
|
||||
goCourseDetail(id) {
|
||||
@ -124,6 +136,22 @@ export default {
|
||||
},
|
||||
err => { })
|
||||
},
|
||||
getLiveStreams() {
|
||||
this.getData("/Membervideo/getLiveStreams", { token: getStore("token") }).then(
|
||||
(data) => {
|
||||
if (data.code == 1) {
|
||||
if (data.data.length > 0) {
|
||||
this.haveLive = true;
|
||||
this.liveData = data.data;
|
||||
}
|
||||
}
|
||||
},
|
||||
(err) => {}
|
||||
);
|
||||
},
|
||||
goLive(room) {
|
||||
this.$router.push({ path: "/liveview?roomName=" + room });
|
||||
},
|
||||
nextLead() {
|
||||
if (this.step == 9) {
|
||||
this.step = 0
|
||||
@ -295,4 +323,25 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.cover {
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.live_box {
|
||||
background-color: white;
|
||||
width: 25rem;
|
||||
box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
|
||||
margin: 3rem;
|
||||
padding: 1rem;
|
||||
border-radius: 10px;
|
||||
cursor: pointer;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
@ -62,7 +62,7 @@
|
||||
{{ loginInfo.member_realname }}_{{ loginInfo.member_passport }}
|
||||
</div>
|
||||
<div id="teacherCamera" class="teacherCamera" ref="teacherCamera"></div>
|
||||
<div class="custom-controls" v-show="showControlBar">
|
||||
<!-- <div class="custom-controls" v-show="showControlBar">
|
||||
<div class="teacherAudioList" v-show="teacherAudioList.length > 0">
|
||||
<div v-for="(teacherAudio, index) in teacherAudioList" class="teacherAudio">
|
||||
{{ teacherAudio.name }}
|
||||
@ -192,7 +192,7 @@
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="menubar">
|
||||
<div class="menubar-one">
|
||||
@ -309,7 +309,7 @@ import { getStore } from "@/utils/storage";
|
||||
import { mapState } from "vuex";
|
||||
import { MessageBox } from "mint-ui";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
QNRTC.setLogLevel(QNLogLevel.NONE);
|
||||
// QNRTC.setLogLevel(QNLogLevel.NONE);
|
||||
export default {
|
||||
components: { Back },
|
||||
data() {
|
||||
@ -467,25 +467,31 @@ export default {
|
||||
}
|
||||
videoTracks[index].play(this.liveContent);
|
||||
|
||||
const videos = document.querySelectorAll(
|
||||
"video.qnrtc-video-player.qnrtc-stream-player"
|
||||
);
|
||||
// 遍历这些元素并添加 controls 属性
|
||||
for (let i = 0; i < videos.length; i++) {
|
||||
//关闭画中画
|
||||
videos[i].disablePictureInPicture = true;
|
||||
// 打破视频宽高比,全部填充
|
||||
videos[i].style.objectFit = "contain";
|
||||
// 关闭右键菜单
|
||||
videos[i].addEventListener("contextmenu", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
//添加水印
|
||||
setTimeout(() => {
|
||||
this.isStop = false;
|
||||
this.isVisible = true;
|
||||
}, 10000);
|
||||
}
|
||||
// 使用 setTimeout 确保视频元素完全创建后再设置控件
|
||||
setTimeout(() => {
|
||||
const videos = document.querySelectorAll(
|
||||
"video.qnrtc-video-player.qnrtc-stream-player"
|
||||
);
|
||||
// 遍历这些元素并添加 controls 属性
|
||||
for (let i = 0; i < videos.length; i++) {
|
||||
videos[i].controls = true;
|
||||
// 确保控件可见
|
||||
videos[i].style.pointerEvents = "auto";
|
||||
//关闭画中画
|
||||
videos[i].disablePictureInPicture = true;
|
||||
// 打破视频宽高比,全部填充
|
||||
videos[i].style.objectFit = "contain";
|
||||
// 关闭右键菜单
|
||||
videos[i].addEventListener("contextmenu", function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
//添加水印
|
||||
setTimeout(() => {
|
||||
this.isStop = false;
|
||||
this.isVisible = true;
|
||||
}, 10000);
|
||||
}
|
||||
}, 100);
|
||||
} else if (videoTracks[index].tag === "video") {
|
||||
const teacherCameraElement = this.$refs.teacherCamera;
|
||||
// 获取所有子元素中的 <video> 标签
|
||||
|
Loading…
x
Reference in New Issue
Block a user