소스 검색

讲义pdf回显,字幕回显,点击字幕视频跳转到对应时间,

canghailong 7 달 전
부모
커밋
944380d77c
3개의 변경된 파일174개의 추가작업 그리고 53개의 파일을 삭제
  1. 57 5
      src/views/student/classCentre/form.vue
  2. 112 5
      src/views/student/classCentre/index.vue
  3. 5 43
      src/views/student/classCentre/rightMenu.vue

+ 57 - 5
src/views/student/classCentre/form.vue

@@ -8,7 +8,13 @@
 		:mask="false"
 	>
 		<div v-if="itemObj.key == 2" style="height: 100%">
-			<vue-office-pdf :src="itemObj.url" style="width: 100%;height: 100%;"  />
+			<vue-office-pdf :src="itemObj.url" style="width: 100%; height: 100%" />
+		</div>
+		<div v-if="itemObj.key == 3" style="height: 100%">
+			<div v-for="(item, idx) in itemObj.srtInfoList" :key="idx">
+				<div>{{ item.startTime }}~{{ item.endTime }}</div>
+				<div style="cursor: pointer; padding: 10px 0" @click="videoSpeed(item)">{{ item.text }}</div>
+			</div>
 		</div>
 		<div v-if="itemObj.type == 2 || itemObj.type == 4">
 			<a-card :bordered="false">
@@ -46,7 +52,8 @@
 	import { required } from '@/utils/formRules'
 	import note from './note.vue'
 	import askDiv from './ask.vue'
-	import VueOfficePdf from '@vue-office/pdf';
+	import VueOfficePdf from '@vue-office/pdf'
+	import axios from 'axios'
 	const props = defineProps({
 		rightItem: {
 			type: [Array, Object],
@@ -57,7 +64,12 @@
 			required: () => {}
 		}
 	})
-	const itemObj = computed(() => props.rightItem)
+	const itemObj = computed(() => {
+		if (props.rightItem?.url) {
+			GetSrtInfo(props.rightItem.url)
+		}
+		return props.rightItem
+	})
 	const noteRef = ref()
 	const submitLoading = ref(false)
 	// 表单数据,也就是默认给一些数据
@@ -67,11 +79,11 @@
 	const activeKey = ref('1')
 	// 默认是关闭状态
 	const visible = ref(false)
-	const emit = defineEmits({ successful: null })
+	const emit = defineEmits({ successful: null, videoSpeed: null })
 	// 打开抽屉
 	const onOpen = (edit) => {
 		visible.value = true
-		if(edit){
+		if (edit) {
 			formData.value = edit
 		}
 	}
@@ -110,6 +122,46 @@
 		onOpen(e)
 		formData.value = e
 	}
+	const videoSpeed = (e) => {
+		emit('videoSpeed', e)
+	}
+	//获取字幕内容,发送一个get请求
+	function GetSrtInfo(srtUrl) {
+		axios
+			.get(`${srtUrl}`)
+			.then(function (response) {
+				let textList = response.data
+					.split(/\n\s\n/)
+					.filter((item) => item != '')
+					.map((item, index) => {
+						let textItem = item.split(/\n/)
+						return {
+							index: index,
+							sort: textItem[0],
+							text: textItem[2],
+							startTime: ToSeconds(textItem[1].split(' --> ')[0]),
+							endTime: ToSeconds(textItem[1].split(' --> ')[1]),
+							timeLine: textItem[1]
+						}
+					})
+				itemObj.value.srtInfoList = textList
+				console.log('解析之后的字幕内容', textList)
+			})
+			.catch(function (error) {
+				console.log(error)
+			})
+	}
+	//将时间转化为秒
+	function ToSeconds(t) {
+		var s = 0.0
+		if (t) {
+			var p = t.split(':')
+			for (let i = 0; i < p.length; i++) {
+				s = s * 60 + parseFloat(p[i].replace(',', '.'))
+			}
+		}
+		return s
+	}
 	// 调用这个函数将子组件的一些数据和方法暴露出去
 	defineExpose({
 		onOpen

+ 112 - 5
src/views/student/classCentre/index.vue

@@ -55,22 +55,31 @@
 						style="height: 900px; width: 100%; background-color: #000"
 						ref="videoRef"
 						controls
-						Controlslist="nodownload noplaybackrate"
+						Controlslist="nodownload noplaybackrate noremoteplayback disablePictureInPicture"
+						@timeupdate="timeUpdate"
+						:currentTime="currentTimenew"
 					>
 						<source :src="videoUrl" type="video/mp4" />
 						<source :src="videoUrl" type="video/ogg" />
 						您的浏览器不支持 HTML5 video 标签。
 					</video>
-					<rightMenu :idsObj="idsObj" :dataList="classTimeData" ref="rightNenuRef"></rightMenu>
+					<rightMenu :idsObj="idsObj" :dataList="classTimeData" ref="rightNenuRef" @videoSpeed="videoSpeed"></rightMenu>
 				</a-card>
 				<a-card :bordered="false" class="mt-2">
 					<a-tabs v-model:activeKey="tabsActiveKey">
 						<a-tab-pane key="1" tab="讲义">
-							<div style="height: 500px">
+							<div style="height: 900px">
 								<vue-office-pdf :src="itemObj.url" style="width: 100%; height: 100%" />
 							</div>
 						</a-tab-pane>
-						<a-tab-pane key="2" tab="字幕">字幕</a-tab-pane>
+						<a-tab-pane key="2" tab="字幕">
+							<div style="height: 900px; overflow-y: auto">
+								<div v-for="(item, idx) in danmuObj.srtInfoList" :key="idx">
+									<div>{{ item.startTime }}~{{ item.endTime }}</div>
+									<div style="cursor: pointer; padding: 10px 0" @click="videoSpeed(item)">{{ item.text }}</div>
+								</div>
+							</div>
+						</a-tab-pane>
 						<a-tab-pane key="3" tab="笔记">
 							<note :idsObj="idsObj" ref="noteRef" @edit="noteEdit"></note>
 						</a-tab-pane>
@@ -92,7 +101,7 @@
 	import note from './note.vue'
 	import askDiv from './ask.vue'
 	import VueOfficePdf from '@vue-office/pdf'
-
+	import axios from 'axios'
 	const route = useRoute()
 	const router = useRouter()
 	const classDetail = ref({})
@@ -102,6 +111,7 @@
 	const selectedKeys = ref([])
 	const collapsed = ref(false)
 	const videoRef = ref()
+	const currentTimenew = ref()
 	const idsObj = computed(() => {
 		let item = findNodeByKey(classTimeList.value, selectedKeys.value[0])
 		return {
@@ -152,7 +162,64 @@
 		let item = classTimeData.value.length > 0 ? classTimeData.value.filter((r) => r.funcType == 2)[0] : { url: '' }
 		return item
 	})
+	const danmuObj = computed(() => {
+		let item = classTimeData.value.length > 0 ? classTimeData.value.filter((r) => r.funcType == 3)[0] : { url: '' }
+		console.log('🚀 ~ item:', item)
+		if (item?.url) {
+			GetSrtInfo(item.url)
+		}
+		return item
+	})
 	const videoUrl = ''
+	const newsschedule = ref(0)
+	const currTime = ref(null)
+	const maxTime = ref(0)
+	const initialtime = ref(0)
+	const videoContext = ref()
+	const timeStamp1 = ref()
+	const allTime = ref()
+	const biNum = ref()
+	const currentTime = ref()
+	const videoStart = () => {
+		videoContext.value = videoRef.value
+		if (initialtime.value > 0) {
+			videoContext.value.currentTime = initialtime.value
+			timeStamp1.value = initialtime.value
+		}
+	}
+	nextTick(() => {
+		videoStart()
+	})
+	const timeUpdate = (e) => {
+		//获取当前播放时间 durationinitialtime
+		if (timeStamp1.value != parseInt(e.target.currentTime)) {
+			allTime.value = parseInt(e.target.duration) //视频总时长(秒)
+			//对播放的时间进行整
+			timeStamp1.value = parseInt(e.target.currentTime) //播放进度 (秒)
+			biNum.value = Math.floor((timeStamp1.value / allTime.value) * 10000) / 100 //暂时没用到
+			currentTime.value = e.target.currentTime
+			if (newsschedule.value < 90) {
+				//newsschedule.value 请求接口获取的参数就是判断当前观看的时长是否小于90 小于90就禁止拖动进度条
+
+				if (e.srcElement.currentTime - currTime.value > 3) {
+					//这里拖动进度条时间 - 当前观看的时长 > 3秒 这边判定它为拖动进度条
+					e.srcElement.currentTime = currTime.value > maxTime.value ? currTime.value : maxTime.value
+					let newsVal = initialtime.value
+					if (newsVal) {
+						videoContext.value.currentTime = newsVal
+					}
+					//当前用户记录观看时间 大于 实施播放时间
+					if (currTime.value > newsVal) {
+						videoContext.value.currentTime = currTime.value
+					}
+					console.log('快进了')
+				}
+				currTime.value = e.srcElement.currentTime
+				maxTime.value = currTime.value > maxTime.value ? currTime.value : maxTime.value
+			}
+		}
+	}
+
 	const rightNenuRef = ref()
 	const noteEdit = (e) => {
 		rightNenuRef.value.selectBtn({ key: 6, type: 2 }, e)
@@ -160,6 +227,46 @@
 	const askEdit = (e) => {
 		rightNenuRef.value.selectBtn({ key: 7, type: 4 }, e)
 	}
+	const videoSpeed = (e) => {
+		currentTimenew.value = e.startTime
+	}
+	//获取字幕内容,发送一个get请求
+	function GetSrtInfo(srtUrl) {
+		axios
+			.get(`${srtUrl}`)
+			.then(function (response) {
+				let textList = response.data
+					.split(/\n\s\n/)
+					.filter((item) => item != '')
+					.map((item, index) => {
+						let textItem = item.split(/\n/)
+						return {
+							index: index,
+							sort: textItem[0],
+							text: textItem[2],
+							startTime: ToSeconds(textItem[1].split(' --> ')[0]),
+							endTime: ToSeconds(textItem[1].split(' --> ')[1]),
+							timeLine: textItem[1]
+						}
+					})
+				danmuObj.value.srtInfoList = textList
+				console.log('解析之后的字幕内容', textList)
+			})
+			.catch(function (error) {
+				console.log(error)
+			})
+	}
+	//将时间转化为秒
+	function ToSeconds(t) {
+		var s = 0.0
+		if (t) {
+			var p = t.split(':')
+			for (let i = 0; i < p.length; i++) {
+				s = s * 60 + parseFloat(p[i].replace(',', '.'))
+			}
+		}
+		return s
+	}
 </script>
 <style scoped lang="less">
 	.classTitle {

+ 5 - 43
src/views/student/classCentre/rightMenu.vue

@@ -8,18 +8,17 @@
 				<div class="fcc">{{ item.title }}</div>
 			</a-menu-item>
 		</a-menu>
-		<rightContent ref="formRef" :idsObj="props.idsObj" :rightItem="rightItem"></rightContent>
+		<rightContent ref="formRef" :idsObj="props.idsObj" :rightItem="rightItem" @videoSpeed="videoSpeed"></rightContent>
 	</div>
 </template>
 
 <script setup name="rightMenu">
 	import classCentre from '@/api/student/classCentre'
 	import rightContent from './form.vue'
-	import axios from 'axios'
 	import { useRoute, useRouter } from 'vue-router'
 	const route = useRoute()
 	const router = useRouter()
-	const emit = defineEmits({ callback: null })
+	const emit = defineEmits({ videoSpeed: null })
 	const props = defineProps({
 		dataList: {
 			type: [Array, Object],
@@ -89,9 +88,6 @@
 		}
 	])
 	const selectBtn = (event, edit) => {
-		if (event.key == 3) {
-			// GetSrtInfo(event.url)
-		}
 		if (event.type == 3) {
 			router.push({
 				path: event.routerUrl,
@@ -108,43 +104,9 @@
 			return match ? { ...r, ...match } : r
 		})
 	})
-	//获取字幕内容,发送一个get请求
-	function GetSrtInfo(srtUrl) {
-		axios
-			.get(`${srtUrl}`)
-			.then(function (response) {
-				console.log('🚀 ~ GetSrtInfo ~ response:', response.data)
-				let textList = response.data
-					.split(/\n\s\n/)
-					.filter((item) => item != '')
-					.map((item, index) => {
-						let textItem = item.split(/\n/)
-						return {
-							index: index,
-							sort: textItem[0],
-							text: textItem[2],
-							startTime: ToSeconds(textItem[1].split(' --> ')[0]),
-							endTime: ToSeconds(textItem[1].split(' --> ')[1]),
-							timeLine: textItem[1]
-						}
-					})
-				btnList.value[2].srtInfoList = textList
-				console.log('解析之后的字幕内容', textList)
-			})
-			.catch(function (error) {
-				console.log(error)
-			})
-	}
-	//将时间转化为秒
-	function ToSeconds(t) {
-		var s = 0.0
-		if (t) {
-			var p = t.split(':')
-			for (let i = 0; i < p.length; i++) {
-				s = s * 60 + parseFloat(p[i].replace(',', '.'))
-			}
-		}
-		return s
+	
+	const videoSpeed = (e) => {
+		emit('videoSpeed', e)
 	}
 	defineExpose({
 		selectBtn