import { closeToast, Icon, Popup, showDialog, showToast } from 'vant'
import {
defineComponent,
onMounted,
reactive,
nextTick,
onUnmounted,
ref,
watch,
Transition,
computed,
onBeforeUnmount,
shallowRef
} from 'vue'
import iconBack from './image/back.png'
import styles from './index.module.less'
import 'plyr/dist/plyr.css'
import request from '@/helpers/request'
import { state } from '@/state'
import { useRoute } from 'vue-router'
import { listenerMessage, postMessage, promisefiyPostMessage } from '@/helpers/native-message'
import qs from 'query-string'
import MusicScore from './component/musicScore'
// import iconDian from './image/icon-dian.svg'
// import iconPoint from './image/icon-point.svg'
import { iconUp, iconDown, iconPen, iconTouping, iconMenu, iconCourseType } from './image/icons.json'
import Points from './component/points'
import { browser } from '@/helpers/utils'
import { Vue3Lottie } from 'vue3-lottie'
import playLoadData from './datas/data.json'
import { usePageVisibility } from '@vant/use'
import { useInterval, useIntervalFn, useNetwork } from '@vueuse/core'
import PlayRecordTime from './playRecordTime'
import { handleCheckVip } from '../hook/useFee'
import OGuide from '@/components/o-guide'
import Tool, { ToolItem, ToolType } from './component/tool'
import Pen from './component/tools/pen'
import VideoItem from './component/video-item'
import deepClone from '@/helpers/deep-clone'
import VideoPlay from './component/video-play'
import CoursewareType from './component/courseware-type'
import CoursewareTips from './component/courseware-tips'
import GlobalTools from '@/components/globalTools'
import { isPlay, penShow, toolOpen, whitePenShow } from '@/components/globalTools/globalTools'
export default defineComponent({
name: 'CoursewarePlay',
setup() {
const pageVisibility = usePageVisibility()
const { isOnline } = useNetwork()
/** 页面显示和隐藏 */
watch(
() => pageVisibility.value,
(value) => {
if (value == 'hidden') {
handleStop()
}
}
)
/** 设置播放容器 16:9 */
const parentContainer = reactive({
width: '100vw'
})
const setContainer = () => {
const min = Math.min(screen.width, screen.height)
const max = Math.max(screen.width, screen.height)
const width = min * (16 / 9)
if (width > max) {
parentContainer.width = '100vw'
return
} else {
parentContainer.width = width + 'px'
}
}
const handleInit = (type = 0) => {
//设置容器16:9
// setContainer()
// 横屏
postMessage(
{
api: 'setRequestedOrientation',
content: {
orientation: type
}
},
() => {
console.log(234)
}
)
// 头,包括返回箭头
// postMessage({
// api: 'setTitleBarVisibility',
// content: {
// status: type
// }
// })
// 安卓的状态栏
postMessage({
api: 'setStatusBarVisibility',
content: {
isVisibility: type
}
})
// 进入页面设置常量
postMessage({
api: 'keepScreenLongLight',
content: {
isOpenLight: type ? true : false
}
})
}
handleInit()
onUnmounted(() => {
handleInit(1)
window.removeEventListener('message', iframeHandle)
})
const route = useRoute()
const headeRef = ref()
const isCurrentCoursewareMenu = shallowRef(true) // 是否为当前选的课程类型
const data = reactive({
currentId: route.query.id as any,
detail: null as any,
knowledgePointList: [] as any,
itemList: [] as any,
lookVideoDataList: [] as any, // 观看视频统计数据
showHead: true,
isCourse: false,
isRecordPlay: false,
videoRefs: {},
refLevelList: [] as any,
videoState: 'init' as 'init' | 'play',
videoItemRef: null as any,
animationState: 'start' as 'start' | 'end',
disableScreenRecordingFlag: '0' // 是否禁止录屏
})
const activeData = reactive({
isAutoPlay: true, // 是否自动播放
nowTime: 0,
model: true, // 遮罩
isAnimation: true, // 是否动画
videoBtns: true, // 视频
currentTime: 0,
duration: 0,
timer: null as any,
item: null as any
})
// 获取缓存路径
const getCacheFilePath = async (material: any) => {
const res = await promisefiyPostMessage({
api: 'getCourseFilePath',
content: {
url: material.content,
localPath: '',
materialId: material.materialId,
updateTime: material.updateTime,
type: material.type // SONG VIDEO IMAGE
}
})
// console.log('缓存路径返回', res)
return res
}
// 获取当前课程是否签退
const getCourseSchedule = async () => {
if (!route.query.courseId) return
try {
const res = await request.get(
`${state.platformApi}/courseSchedule/detail/${route.query.courseId}`,
{
hideLoading: true
}
)
if (res?.data) {
data.isCourse =
res.data.status === 'ING' && state.platformType == 'TEACHER' ? true : false
// data.isRecordPlay = Date.now() > dayjs(res.data.startTime).valueOf()
}
} catch (e) {
console.log(e)
}
}
const getTempList = async (materialList: any, name: any) => {
const list: any = []
const browserInfo = browser()
for (let j = 0; j < materialList.length; j++) {
const material = materialList[j]
//请求本地缓存
if (browserInfo.isApp && ['VIDEO', 'IMG'].includes(material.type)) {
const localData = await getCacheFilePath(material)
if (localData?.content?.localPath) {
material.url = material.content
material.content = localData.content.localPath
}
}
const videoData = data.lookVideoDataList.find(
(i: any) => i.materialId === material.materialId
)
material.moreTime = videoData?.videoBrowseData ? JSON.parse(videoData.videoBrowseData) : []
material.videoTime = videoData?.videoTime || 0 // 视频时长
material.iframeRef = null
material.videoEle = null
material.tabName = name
material.autoPlay = false //加载完成是否自动播放
material.isprepare = false // 视频是否加载完成
material.isRender = false // 是否渲染了
list.push(material)
// list.push({
// ...material,
// moreTime: videoData?.videoBrowseData ? JSON.parse(videoData.videoBrowseData) : [],
// videoTime: videoData?.videoTime || 0, // 视频时长
// iframeRef: null,
// videoEle: null,
// tabName: name,
// autoPlay: false, //加载完成是否自动播放
// isprepare: false, // 视频是否加载完成
// isRender: false // 是否渲染了
// })
}
return list
}
const getItemList = async () => {
const list: any = []
for (let i = 0; i < data.knowledgePointList.length; i++) {
const item = data.knowledgePointList[i]
if (item.materialList && item.materialList.length > 0) {
const tempList = await getTempList(item.materialList, item.name)
list.push(...tempList)
}
// 第二层级
if (item.children && item.children.length > 0) {
const childrenList = item.children || []
for (let j = 0; j < childrenList.length; j++) {
const childItem = childrenList[j]
const tempList = await getTempList(childItem.materialList, childItem.name)
list.push(...tempList)
}
}
}
// console.log(list, 'list')
let _firstIndex = list.findIndex(
(n: any) =>
n.knowledgePointMaterialRelationId == route.query.kId || n.materialId == route.query.kId
)
_firstIndex = _firstIndex > -1 ? _firstIndex : 0
const item = list[_firstIndex]
// console.log(_firstIndex, '_firstIndex', route.query.kId, 'route.query.kId', item)
// 是否自动播放
if (activeData.isAutoPlay) {
item.autoPlay = true
}
popupData.activeIndex = _firstIndex
popupData.playIndex = _firstIndex
popupData.tabName = item.tabName
popupData.tabActive = item.knowledgePointId
popupData.itemActive = item.id
popupData.itemName = item.name
nextTick(() => {
data.itemList = list
checkedAnimation(popupData.activeIndex)
postMessage({
api: 'courseLoading',
content: {
show: false,
type: 'fullscreen'
}
})
//检测是否录屏
if (data.disableScreenRecordingFlag === '1') {
handleLimitScreenRecord()
}
setTimeout(() => {
data.animationState = 'end'
}, 500)
})
}
const getDetail = async (id?: any) => {
try {
const res: any = await request.get(
state.platformApi + `/lessonCoursewareDetail/detail/${id || route.query.id}`,
{
hideLoading: true
}
)
const result = res.data || {}
result.lessonTargetDesc = result.lessonTargetDesc ? result.lessonTargetDesc.replace(/\n/g, "
") : ""
data.detail = result;
if (res?.data?.lockFlag) {
postMessage({
api: 'courseLoading',
content: {
show: false,
type: 'fullscreen'
}
})
showDialog({
title: '温馨提示',
message: '课件已锁定'
}).then(() => {
goback()
})
return
}
if (Array.isArray(res?.data?.knowledgePointList)) {
let index = 0
data.knowledgePointList = res.data.knowledgePointList.map((n: any) => {
if (Array.isArray(n.materialList)) {
n.materialList = n.materialList.map((item: any) => {
index++
const materialRefs = item.materialRefs ? item.materialRefs : []
const materialMusicId = materialRefs.length > 0 ? materialRefs[0].resourceId : null
return {
...item,
materialMusicId,
knowledgePointId: [item.knowledgePointId],
materialId: item.id,
id: index + ''
}
})
}
if (Array.isArray(n.children)) {
n.children = n.children.map((cn: any) => {
cn.materialList = cn.materialList.map((item: any) => {
index++
const materialRefs = item.materialRefs ? item.materialRefs : []
const materialMusicId =
materialRefs.length > 0 ? materialRefs[0].resourceId : null
return {
...item,
materialMusicId,
knowledgePointId: [n.id, item.knowledgePointId],
materialId: item.id,
id: index + ''
}
})
return cn
})
}
return n
})
getItemList()
}
return true
} catch (error) {
console.log(error)
}
}
const onTitleTip = (type: "phaseGoals" | "checkItem", text: string) => {
handleStop()
popupData.pointOpen = true
popupData.pointContent = text
if(type === "checkItem") {
popupData.pointTitle = '检查事项'
} else if(type === "phaseGoals") {
popupData.pointTitle = '阶段目标'
}
}
// ifram事件处理
const iframeHandle = (ev: MessageEvent) => {
if (ev.data?.api === 'headerTogge') {
activeData.model = ev.data.show || (ev.data.playState == 'play' ? false : true)
}
}
// 获取学生观看数据
const getLookVideoData = async () => {
try {
const res = await request.get(
state.platformApi + `/studentCoursewareMaterialRelation/findByDetailId`,
{
hideLoading: true,
params: {
lessonCoursewareDetailId: route.query.id
}
}
)
data.lookVideoDataList = res.data || [] // 视频播放数据
} catch {
//
}
}
// 切换播放
const togglePlay = (m: any, isPlay: boolean) => {
if (isPlay) {
m.videoEle?.play()
} else {
m.videoEle?.pause()
}
}
let timers: any = null
const checkVideoPlay = () => {
const activeVideoRef = data.videoItemRef?.getPlyrRef()
if (activeVideoRef) {
timers = setInterval(() => {
if (!activeVideoRef.paused()) {
activeVideoRef.pause()
clearInterval(timers)
}
activeVideoRef.pause()
}, 100)
}
setTimeout(() => {
clearInterval(timers)
}, 3000)
}
//录屏时间触发
const handleLimitScreenRecord = async () => {
const result = await promisefiyPostMessage({
api: 'getDeviceStatus',
content: { type: 'video' }
})
const { status } = result?.content || {}
if (status == '1') {
data.itemList.forEach((item: any) => (item.autoPlay = false))
handleStop()
// 处理事件 - 事件事件后加载的
checkVideoPlay()
showDialog({
title: '温馨提示',
message: '课件内容请勿录屏',
beforeClose: () => {
return new Promise((resolve) => {
promisefiyPostMessage({
api: 'getDeviceStatus',
content: { type: 'video' }
}).then((res: any) => {
const content = res.content
if (content?.status == '1') {
const activeItem = data.itemList[popupData.activeIndex]
togglePlay(activeItem, false)
resolve(false)
} else {
const activeItem = data.itemList[popupData.activeIndex]
togglePlay(activeItem, true)
resolve(true)
}
})
})
}
})
}
}
// 获取禁止录屏
const sysParamConfig = async () => {
try {
const res = await request.get(`${state.platformApi}/sysParamConfig/queryByParamName`, {
params: {
paramName: 'disable_screen_recording_flag'
}
})
data.disableScreenRecordingFlag = res.data.paramValue || ''
} catch {
//
}
}
const getRefLevel = async (id?: any) => {
try {
const res = await request.post(state.platformApi + '/lessonCoursewareDetail/refLevel', {
data: {
lessonCoursewareDetailId: id || route.query.id
}
})
data.refLevelList = res.data || []
return true
} catch {
//
}
}
onMounted(async () => {
await sysParamConfig()
if (state.platformType === 'STUDENT') {
await getLookVideoData()
}
// 只有老师有 课程类型 切换
if(state.platformType === "TEACHER") {
await getRefLevel()
}
await getDetail()
const hasFree = String(data.detail?.accessScope) === '0'
if (!hasFree) {
const hasVip = handleCheckVip()
if (!hasVip) {
nextTick(() => {
postMessage({
api: 'courseLoading',
content: {
show: false,
type: 'fullscreen'
}
})
})
return
}
}
getCourseSchedule()
window.addEventListener('message', iframeHandle)
if (data.disableScreenRecordingFlag === '1') {
//禁止录屏 ios
listenerMessage('setVideoPlayer', (result) => {
if (result?.content?.status == 'pause') {
handleLimitScreenRecord()
}
})
// 安卓
postMessage({
api: 'limitScreenRecord',
content: {
type: 1
}
})
}
})
onBeforeUnmount(() => {
postMessage({
api: 'limitScreenRecord',
content: {
type: 0
}
})
})
const playRef = ref()
// 返回
const goback = () => {
try {
playRef.value?.handleOut()
} catch (error) {
console.log(error)
}
postMessage({ api: 'goBack' })
}
const popupData = reactive({
pointOpen: false,
pointContent: "",
pointTitle: "",
coursewareOpen: false,
open: false,
activeIndex: 0,
playIndex: 0,
tabActive: '',
tabName: '',
itemActive: '',
itemName: '',
guideOpen: false,
toolOpen: false // 工具弹窗控制
})
const stopVideo = (el: HTMLVideoElement) => {
return new Promise((resolve) => {
if (el.paused) return resolve(true)
el.onpause = () => {
console.log('暂停')
resolve(true)
}
el.pause()
})
}
/**停止所有的播放 */
const handleStop = () => {
for (let i = 0; i < data.itemList.length; i++) {
const activeItem = data.itemList[i]
if (activeItem.type === 'VIDEO') {
// activeItem.videoEle?.currentTime(0)
activeItem.videoEle?.pause()
// activeItem.videoEle?.stop()
}
// 停止曲谱的播放
if (activeItem.type === 'SONG') {
activeItem.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
}
}
console.log('视频暂停完成')
data.itemList.forEach((item: any) => {
if (item.type === 'SONG') {
item.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
}
})
}
// 切换素材
const toggleMaterial = (itemActive: any) => {
const index = data.itemList.findIndex((n: any) => n.id == itemActive)
if (index > -1) {
handleSwipeChange(index)
}
}
/** 延迟收起模态框 */
const setModelOpen = () => {
clearTimeout(activeData.timer)
closeToast()
activeData.timer = setTimeout(() => {
activeData.model = false
}, 4000)
}
/** 立即收起所有的模态框 */
const clearModel = () => {
clearTimeout(activeData.timer)
closeToast()
activeData.model = false
}
const toggleModel = (type = true) => {
activeData.model = type
}
// 去点名,签退
const gotoRollCall = (pageTag: string) => {
postMessage({
api: 'open_app_page',
content: {
action: 'app',
pageTag: pageTag,
url: '',
params: JSON.stringify({ courseId: route.query.courseId })
}
})
}
// 双击
const handleDbClick = () => {
if (activeVideoItem.value.type === 'VIDEO') {
const activeVideoRef = data.videoItemRef?.getPlyrRef()
if (activeVideoRef) {
if (activeVideoRef.paused()) {
activeVideoRef.play()
} else {
activeVideoRef.pause()
showToast('已暂停')
}
}
}
}
const effectIndex = ref(0)
const effects = [
{
prev: {
transform: 'translate3d(0, 0, -800px) rotateX(180deg)'
},
next: {
transform: 'translate3d(0, 0, -800px) rotateX(-180deg)'
}
},
{
prev: {
transform: 'translate3d(-100%, 0, -800px)'
},
next: {
transform: 'translate3d(100%, 0, -800px)'
}
},
{
prev: {
transform: 'translate3d(-50%, 0, -800px) rotateY(80deg)'
},
next: {
transform: 'translate3d(50%, 0, -800px) rotateY(-80deg)'
}
},
{
prev: {
transform: 'translate3d(-100%, 0, -800px) rotateY(-120deg)'
},
next: {
transform: 'translate3d(100%, 0, -800px) rotateY(120deg)'
}
},
// 风车4
{
prev: {
transform: 'translate3d(-50%, 50%, -800px) rotateZ(-14deg)',
opacity: 0
},
next: {
transform: 'translate3d(50%, 50%, -800px) rotateZ(14deg)',
opacity: 0
}
},
// 翻页5
{
prev: {
transform: 'translateZ(-800px) rotate3d(0, -1, 0, 90deg)',
opacity: 0
},
next: {
transform: 'translateZ(-800px) rotate3d(0, 1, 0, 90deg)',
opacity: 0
},
current: { transitionDelay: '700ms' }
}
]
const acitveTimer = ref()
// 轮播切换
const handleSwipeChange = async (index: number) => {
// 如果是当前正在播放 或者是视频最后一个
if (popupData.activeIndex == index) return
await handleStop()
data.animationState = 'start'
data.videoState = 'init'
clearTimeout(acitveTimer.value)
checkedAnimation(popupData.activeIndex, index)
nextTick(() => {
popupData.activeIndex = index
acitveTimer.value = setTimeout(
() => {
popupData.playIndex = index
const item = data.itemList[index]
if (item) {
popupData.tabActive = item.knowledgePointId
popupData.itemActive = item.id
popupData.itemName = item.name
popupData.tabName = item.tabName
if (item.type == 'SONG') {
activeData.model = true
}
}
if (item.type === 'VIDEO') {
// 自动播放下一个视频
clearTimeout(activeData.timer)
closeToast()
item.autoPlay = true
// console.log(item, 'item')
// 当视屏异常时重置链接
if (item.error) {
item.videoEle?.src(item.content)
item.error = false
}
nextTick(() => {
item.videoEle?.play()
})
}
requestAnimationFrame(() => {
const _effectIndex = effectIndex.value + 1
effectIndex.value = _effectIndex >= effects.length - 1 ? 0 : _effectIndex
})
},
activeData.isAnimation ? 800 : 0
)
})
}
/** 是否有转场动画 */
const checkedAnimation = (index: number, nextIndex?: number) => {
nextIndex = nextIndex ? nextIndex : index + 1
const item = data.itemList[index]
const nextItem = data.itemList[nextIndex]
if (nextItem) {
if (nextItem.knowledgePointId != item.knowledgePointId) {
activeData.isAnimation = true
return
}
const videoEle = item.videoEle
const nextVideo = nextItem.videoEle
if (videoEle && videoEle.duration < 8 && index < nextIndex) {
activeData.isAnimation = false
} else if (nextVideo && nextVideo.duration < 8 && index > nextIndex) {
activeData.isAnimation = false
} else {
activeData.isAnimation = true
}
} else {
activeData.isAnimation = item?.adviseStudyTimeSecond < 8 ? false : true
}
}
// 上一个知识点, 下一个知识点
const handlePreAndNext = (type: string) => {
if (type === 'up') {
handleSwipeChange(popupData.activeIndex - 1)
} else {
handleSwipeChange(popupData.activeIndex + 1)
}
}
/** 弹窗关闭 */
const handleClosePopup = () => {
const item = data.itemList[popupData.activeIndex]
if (item?.type == 'VIDEO' && !item.videoEle?.paused) {
setModelOpen()
}
}
/** 教学数据 */
const studyData = reactive({
type: '' as ToolType,
penShow: false
})
/** 打开教学工具 */
const openStudyTool = (item: ToolItem) => {
const activeItem = data.itemList[popupData.activeIndex]
// 暂停视频和曲谱的播放
if (activeItem.type === 'VIDEO' && activeItem.videoEle) {
activeItem.videoEle.pause()
}
if (activeItem.type === 'SONG') {
activeItem.iframeRef?.contentWindow?.postMessage({ api: 'setPlayState' }, '*')
}
clearModel()
popupData.toolOpen = false
studyData.type = item.type
switch (item.type) {
case 'pen':
studyData.penShow = true
break
}
}
/** 关闭教学工具 */
const closeStudyTool = () => {
studyData.type = 'init'
toggleModel()
}
const activeVideoItem = computed(() => {
const item = data.itemList[popupData.activeIndex]
if (item && item.type && item.type.toLocaleUpperCase() === 'VIDEO') {
return item
}
return {}
})
let closeModelTimer: any = null
/**
* 统计视频播放时间段
*/
const intervalFnRef = ref() // 定时任务
// 播放视频总时长
const videoIntervalRef = useInterval(1000, { controls: true })
videoIntervalRef.pause()
/**
* 格式化视屏播放有效时间 - 合并区间
* @param intervals [[], []]
* @example [[4, 8],[0, 4],[10, 30]]
* @returns [[0, 8], [10, 30]]
*/
const formatEffectiveTime = (intervals: any[]) => {
const res: any = []
intervals.sort((a, b) => a[0] - b[0])
let prev = intervals[0]
for (let i = 1; i < intervals.length; i++) {
const cur = intervals[i]
if (prev[1] >= cur[0]) {
// 有重合
prev[1] = Math.max(cur[1], prev[1])
} else {
// 不重合,prev推入res数组
res.push(prev)
prev = cur // 更新 prev
}
}
res.push(prev)
// console.log(res, 'formatEffectiveTime')
return res
}
/**
* 获取数据有效期
* @param intervals [[], []]
* @returns 0s
*/
const formatTimer = (intervals: any[]) => {
const afterIntervals = formatEffectiveTime(intervals)
let time = 0
afterIntervals.forEach((t: any) => {
time += t[1] - t[0]
})
return time
}
// 保存零时时间
// const moreTime: any = ref([]) // 多个观看时间段 已经放到列表里面了
let tempTime: any = [] // 临时存储时间
const currentTimer = useInterval(1000, { controls: true })
// 监听播放状态,
watch(
() => videoIntervalRef.isActive.value,
(newVal: boolean) => {
initVideoCount(newVal)
}
)
// 白板的批注打开时暂停播放
watch(
() => [whitePenShow.value, penShow.value],
() => {
if (whitePenShow.value || penShow.value) {
handleStop()
}
}
)
// 是否收起
watch(
() => activeData.model,
() => {
if (activeData.model) {
isPlay.value = false
} else {
isPlay.value = true
toolOpen.value = false
}
}
)
/**
* 初始化视频时长
* @param newVal 播放状态
* @param repeat 是否为定时发送的
*/
const initVideoCount = (newVal: any, repeat = false) => {
// console.log('watch', forms.player.currentTime)
const activeVideoRef = data.videoItemRef?.getPlyrRef()
const initTime = deepClone(tempTime)
if (repeat) {
if (tempTime.length > 0) {
// console.log('join video', tempTime, 'initTime', initTime)
tempTime[1] = Math.floor(activeVideoRef.currentTime())
}
} else {
if (newVal) {
tempTime[0] = Math.floor(activeVideoRef.currentTime())
} else {
tempTime[1] = Math.floor(activeVideoRef.currentTime())
}
}
if (tempTime.length >= 2) {
// console.log(tempTime, 'tempTime', moreTime.value)
// 处理在短时间内的时间差 【视屏拖动,点击可能会导致时间差太大】
const diffTime = tempTime[1] - tempTime[0] - currentTimer.counter.value > 2
// 结束时间,如果 大于开始时间则清除
if (tempTime[1] >= tempTime[0] && !diffTime) {
data.itemList[popupData.activeIndex].moreTime.push(tempTime)
// moreTime.value.push(tempTime)
}
if (repeat) {
tempTime = deepClone(initTime)
} else {
tempTime = []
currentTimer.counter.value = 0
}
}
}
// 更新时间
const updateStat = async () => {
try {
const itemList = data.itemList
const params: any = []
itemList.forEach((item: any) => {
if (item.moreTime.length > 0) {
const videoBrowseData = formatEffectiveTime(item.moreTime)
const time = videoBrowseData.length > 0 ? formatTimer(videoBrowseData) : 0
const temp = {
lessonCoursewareDetailId: route.query.id,
browseTime: time, // 播放时长
videoBrowseData: JSON.stringify(videoBrowseData), // 播放的数据
videoTime: item.videoTime, // 视频时长
materialId: item.materialId
}
params.push(temp)
}
})
// 只有学生才统计数据
if (params.length > 0 && state.platformType === 'STUDENT') {
await request.post(`${state.platformApi}/studentCoursewareMaterialRelation/save`, {
data: params
})
}
} catch {
//
}
}
onMounted(() => {
// 间隔多少时间同步数据
intervalFnRef.value = useIntervalFn(async () => {
// 同步数据时先进行有效时间进行保存
initVideoCount(false, true)
await updateStat()
videoIntervalRef.counter.value = 0
}, 10000)
})
/** 统计视频播放时间段 */
return () => (
goback()}>{data.itemList[popupData.activeIndex]?.name}
{data.detail?.lessonTargetDesc ? onTitleTip('phaseGoals', data.detail?.lessonTargetDesc)}>阶段目标: ""} {data.itemList[popupData.activeIndex]?.checkItem ? onTitleTip('checkItem', data.itemList[popupData.activeIndex]?.checkItem)}>检查事项 : ""}