jy-safe-app/pages/apply/subPages/SCWB/wb008_OPERATENEW.nvue
2025-10-14 15:17:30 +08:00

890 lines
25 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- #ifdef APP-PLUS -->
<view class="wrap">
<view class="player" v-if="filepath.length > 0&&isOnline">
<plv-player ref="vod" class="vod-player" seekType="0" autoPlay="true" disableScreenCAP="false" rememberLastPosition="true" @onPlayStatus="onPlayStatus" @onPlayError="onPlayError"
@positionChange="positionChange"></plv-player>
</view>
<view class="controls-contain">
<view class="floating-controls">
<view class="abs-box">
<view style="display: flex;align-items: center;justify-content: center;flex-direction: row;margin-bottom: 5px;">
<view @click="togglePlayLow" style="display: flex;flex-direction: row;">
<u-icon name="rewind-left" size="26px" color="#fff"></u-icon>
<text style="color: #fff;font-size: 12px;">5s</text>
</view>
<view @click="togglePlay" class="playing-icon">
<u-icon name="pause-circle" size="26px" color="#fff" v-if="isPlaying"></u-icon>
<u-icon name="play-circle" size="26px" color="#fff" v-else></u-icon>
</view>
<view @click="togglePlayFast">
<u-icon name="rewind-right" size="26px" color="#c4c6c9"></u-icon>
</view>
</view>
<view class="progress-container">
<view class="time-text">
<text style="font-size: 14px;color: #fff;">{{currentTimeText}}</text>
</view>
<view class="progress-bar" @click="seekByProgressBar($event)">
<u-slider v-model="sliderValue " blockSize="12" @change="changeseek"></u-slider>
</view>
<view class="time-text">
<text style="font-size: 14px;color: #fff;">{{totalTime }}</text>
</view>
</view>
</view>
</view>
</view>
<view v-if="isVodeoEnd" style="background-color: #fff;margin: 20px 20px 0px 20px;padding: 20px;border-radius: 5px;flex: 1;">
<scroll-view class="scrollable-content" scroll-y="true" style="flex: 1;" show-scrollbar="false">
<u--form labelPosition="left" labelWidth="auto" labelAlign="center" errorType="border-bottom" ref="sForm" class="demo-ruleForm">
<view v-for="(item, index) in papers" :key="index" style="border-bottom: #ceccca 1px dashed;margin-bottom: 10px;padding-bottom: 10px;">
<!-- <u-form-item> -->
<view style="display: flex;flex: 1;">
<view style="display: flex; word-wrap: break-word; word-break: break-all;margin-bottom: 10px;white-space: normal;">
<text style="font-size: 15px;">
{{(index + 1) + '. ' + item.Nav_Test.NAME + getType(item)}}
</text>
</view>
<view class="operate-radio">
<u-radio-group v-if="item.Nav_Test.TYPE == 0" v-model="item.ANSWER1" placement="column">
<u-radio :customStyle="{marginBottom: '4px',marginTop: '4px'}" v-for="(item1, index1) in radiolist1" :key="index1" :label="item1.name" :name="item1.name"
@change="doOptionChange(index1, item, 1)" :disabled="readonly" />
</u-radio-group>
<u-radio-group v-if="item.Nav_Test.TYPE == 1" v-model="item.ANSWER2" placement="column">
<u-radio :customStyle="{marginBottom: '4px',marginTop: '4px',whiteSpace:'normal',wordBreak: 'break-all'}" v-for="(item2, index2) in radiolist2[item.ID]" :key="index2"
:label="item2.name" :name="item2.name" @change="doOptionChange(index2, item, 1 << index2)" :disabled="readonly" />
</u-radio-group>
<u-checkbox-group v-if="item.Nav_Test.TYPE == 2" v-model="item.ANSWER3" @change="checkboxChange($event, item)" placement="column">
<u-checkbox :customStyle="{marginBottom: '4px',marginTop: '4px',whiteSpace:'normal !important',wordBreak: 'break-all !important'}" v-for="(item3, index3) in radiolist2[item.ID]"
:key="index3" :label="item3.name" :name="item3.name" :disabled="readonly">
</u-checkbox>
</u-checkbox-group>
</view>
</view>
<!-- </u-form-item> -->
</view>
</u--form>
</scroll-view>
</view>
<view v-else style="flex: 1;display: flex;align-items: center;justify-content: center;">
<text style="color: #c4c6c9;font-size: 14px;">视频播放完毕后,开始答题</text>
</view>
<view class="bottom-button-new">
<button type="primary" v-if="tableKey == 1" @click="submit" :disabled="!isVodeoEnd">提交问卷</button>
</view>
</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<view class="todo-page" style="padding-bottom: 80px;">
<view class="background"></view>
<view class="video" v-if="filepath.length > 0&&isOnline">
<uni-card margin="0" :is-shadow="true">
<u--form labelPosition="left" labelWidth="auto" labelAlign="center" ref="wForm" errorType="border-bottom">
<view style=" position: relative;z-index: 1;" v-if="polyvy">
<webPlayer :src="filepaths" @over="onEnd()"></webPlayer>
</view>
<view v-else>
<video id="myVideo" @ended="onEnd()" @timeupdate="onTimeUpdate" :src="filepathsWeb" controls></video>
</view>
</u--form>
</uni-card>
</view>
<view v-if="isVodeoEnd" class="card">
<u--form labelPosition="left" labelWidth="auto" labelAlign="center" errorType="border-bottom" ref="sForm" class="demo-ruleForm">
<view style="position: relative;">
<view style="position: absolute;left: -10px;color: #3d4b70;top: -3px;">*</view>
</view>
<view style="font-size: 15px; font-weight: bold;color: #3d4b70;margin-bottom: 10px;">培训教育在线答题</view>
<view v-for="(item, index) in papers" :key="index" style="border-bottom: #ceccca 1px dashed;margin-bottom: 10px;padding-bottom: 10px;">
<u-form-item>
<view style="display: flex;flex: 1;">
<view style="display: flex; word-wrap: break-word; word-break: break-all;margin-bottom: 10px;white-space: normal;">{{(index + 1) + '. ' + item.Nav_Test.NAME + getType(item)}}
</view>
<view>
<u-radio-group v-if="item.Nav_Test.TYPE == 0" v-model="item.ANSWER1" placement="column">
<u-radio :customStyle="{marginBottom: '4px',marginTop: '4px',whiteSpace:'normal',wordBreak: 'break-all',}" v-for="(item1, index1) in radiolist1" :key="index1" :label="item1.name"
:name="item1.name" @change="doOptionChange(index1, item, 1)" :disabled="readonly" />
</u-radio-group>
<u-radio-group v-if="item.Nav_Test.TYPE == 1" v-model="item.ANSWER2" placement="column">
<u-radio :customStyle="{marginBottom: '4px',marginTop: '4px',whiteSpace:'normal',wordBreak: 'break-all',}" v-for="(item2, index2) in radiolist2[item.ID]" :key="index2"
:label="item2.name" :name="item2.name" @change="doOptionChange(index2, item, 1 << index2)" :disabled="readonly" />
</u-radio-group>
<u-checkbox-group v-if="item.Nav_Test.TYPE == 2" v-model="item.ANSWER3" @change="checkboxChange($event, item)" placement="column">
<u-checkbox :customStyle="{marginBottom: '4px',marginTop: '4px'}" v-for="(item3, index3) in radiolist2[item.ID]" :key="index3" :label="item3.name" :name="item3.name"
:disabled="readonly" class="checkbox">
</u-checkbox>
</u-checkbox-group>
</view>
</view>
</u-form-item>
</view>
</u--form>
</view>
<view class="bottom-button">
<button type="primary" v-if="tableKey == 1" @click="submit" :disabled="!isVodeoEnd">提交问卷</button>
</view>
</view>
<!-- #endif -->
</template>
<script>
// #ifdef APP-PLUS
var configModule = uni.requireNativePlugin("PLV-VodUniPlugin-ConfigModule")
// #endif
import {
extendFilterGroup,
extendGroupRule,
extendInclude,
extendOrder,
extendRule,
guid,
initFilter,
initFilterGroup,
formatSeconds
} from '../../../../utils/common';
import {
getRequest,
} from '../../../../services/apply/FOServices/FOServices';
import {
GetSource,
SavePapers
} from '../../../../services/apply/subPages/scWB';
import webPlayer from './webPlayer'
import config from '../../../../config/common';
export default {
components: {
webPlayer, // 注册组件
},
data() {
return {
model: {
ORG_ID: "",
},
SOURCE_ID: '',
papers: [],
res: [],
viewAll: false,
filepath: '',
notify: null,
UserList: [],
SelUsrID: null,
config: null,
score: 0,
END_TIME: null,
readonly: true,
loading: true,
tableKey: '0',
isHaseV: true,
isVodeoEnd: false, //是否显示题目
radiolist1: [{
name: '正确',
disabled: false
},
{
name: '错误',
disabled: false
},
],
radiolist2: {},
radiovalue1: "错误",
checkbox: [],
TaskID: '',
SelUsrNAME: '',
ORG_ID: uni.getStorageSync('orgId'),
JOBID: '',
progress: 0,
currentTime: '',
allTime: '',
lastTime: 0,
playerUrl: '',
vid: '', // 解析后的视频ID,
plvConfig: {
userid: "3cbccb39d9",
readtoken: "4567132a-70d2-4a92-a1e5-5a417fe4ab5b",
writetoken: "007263ef-a7ee-4681-b248-395d1da539b9",
secretkey: "WUAYy8sr4"
},
// 新增状态变量
isPlaying: false, // 是否正在播放
currentTime: 0, // 当前播放时间(秒)
totalTime: 0, // 总时长(秒)
currentTimeText: 0,
progressPercent: 0, // 进度百分比
duration: 0,
sliderValue: 0,
timeShowBlock: true,
now: 'init',
filepaths: '',
filepathsWeb: '',
polyvy: true,
}
},
onLoad(option) {
this.TaskID = option.taskID ? option.taskID : '';
this.model.ID = option.ID ? option.ID : '';
this.JOBID = option.ID ? option.ID : '';
this.tableKey = option.tableKey ? option.tableKey : '0'
// #ifdef APP-PLUS
if (!configModule) {
this.$emit('onError', '插件初始化失败');
return;
}
configModule.setToken({
userid: "3cbccb39d9",
readtoken: "4567132a-70d2-4a92-a1e5-5a417fe4ab5b",
writetoken: "007263ef-a7ee-4681-b248-395d1da539b9",
secretkey: "WUAYy8sr4"
}, (ret) => {
if (!ret.isSuccess) {
this.$emit('onError', ret.errMsg);
}
});
this.totalTime = this.formatTime(0);
this.currentTimeText = this.formatTime(0)
// #endif
this.loadData();
},
watch: {
// 监听 filepaths 的变化
filepaths(newVal, oldVal) {
if (newVal) {
const regex = /vid=([^&]+)/;
const match = newVal.match(regex);
this.vid = match ? match[1] : '';
this.now = 'init'
if (oldVal !== '') {
this.togglePlay()
}
}
},
},
methods: {
togglePlay() {
if (this.now == 'init') {
this.$refs.vod.setVid({
vid: this.vid,
level: 0
},
(ret) => {
if (ret.errMsg != null) {
uni.showToast({
title: ret.errMsg,
icon: "none"
})
}
})
this.now = 'playing'
} else {
if (this.isPlaying) {
// 调用暂停API需确认保利威插件实际方法名可能为pause/stop
this.$refs.vod.pause();
} else {
this.$refs.vod.start();
}
}
},
changeseek(e) {
// 将0-100的滑块值转换为对应的视频时间(秒)
const seekTime = Math.round((e / 100) * this.duration);
if (seekTime < this.currentTime) {
this.$refs.vod.seekTo({
seconds: seekTime
},
(ret) => {
if (ret.errMsg != null) {
uni.showToast({
title: ret.errMsg,
icon: "none"
})
}
})
} else {
uni.$showErrorInfo('培训答题视频禁止快进');
}
},
togglePlayLow() {
this.$refs.vod.rewind({
seconds: 5
},
(ret) => {
if (ret.errMsg != null) {
uni.showToast({
title: ret.errMsg,
icon: "none"
})
}
})
},
togglePlayFast() {
uni.$showErrorInfo('培训答题视频禁止快进');
},
setVid() {
this.$refs.vod.setVid({
vid: this.vid,
level: 0
},
(ret) => {
if (ret.errMsg != null) {
uni.showToast({
title: ret.errMsg,
icon: "none"
})
}
})
},
onPlayStatus(e) {
const status = e.detail.playbackState;
// 根据保利威状态枚举更新播放状态(需参考插件文档,示例值)
this.isPlaying = status == 'start'
// 视频结束时更新状态
if (status == 'complete') {
this.isPlaying = false;
this.isVodeoEnd = true;
}
if (e.detail.preparedToPlay !== null) {
this.updateDuration();
}
this.$forceUpdate()
},
updateDuration() {
this.$refs.vod.getDuration(null, ret => {
this.duration = ret.duration;
this.timeShowBlock = ret.duration >= 3600 ? false : true;
});
},
positionChange(e) {
this.timeUpdate(e.detail.currentPosition);
},
timeUpdate(time) {
this.currentTime = time;
this.updateProgress();
},
updateProgress(precent) {
// this.currentTime = e.detail.currentPosition;
this.totalTime = this.formatTime(this.duration);
this.currentTimeText = this.formatTime(this.currentTime)
// 将当前播放时间(秒)转换为0-100的滑块值
this.sliderValue = (this.currentTime / this.duration) * 100;
// 计算进度百分比
// this.progressPercent = this.duration > 0 ? (this.currentTime / this.duration) * 100 : 0;
this.$forceUpdate()
},
// 格式化时间(秒 -> MM:SS
formatTime(seconds) {
if (this.timeShowBlock == true) {
const min = Math.floor(seconds / 60);
const sec = Math.floor(seconds % 60);
return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
} else {
const hours = Math.floor(seconds / 3600);
// 计算剩余秒数,再 ÷ 60 得到分钟
const minutes = Math.floor((seconds % 3600) / 60);
// 剩余的秒数
const remainingSeconds = seconds % 60;
// 拼接并补零
return `${this.padZero(hours)}:${this.padZero(minutes)}:${this.padZero(remainingSeconds)}`;
}
},
padZero(num) {
return num < 10 ? '0' + num : num;
},
// 点击进度条跳转播放位置
seekByProgressBar(e) {
// const player = this.$refs.vod;
if (this.totalTime <= 0) return;
// 获取进度条宽度和点击位置
const barWidth = e.currentTarget.clientWidth;
const clickX = e.touches[0].clientX - e.currentTarget.getBoundingClientRect().left;
// 计算跳转时间
const seekTime = (clickX / barWidth) * this.totalTime;
// 调用播放器跳转API需确认方法名可能为seek/setPosition
this.$refs.vod.seekTo({
position: seekTime
});
},
loadData() {
let json = initFilter(this.ORG_ID, this.model.ID);
extendRule(json, 'ID', 1, this.model.ID);
GetSource(json).then(ret => {
if (ret) {
this.loading = false
var filepath = ''
var isOnline = false
var papers = []
var SOURCE_ID = ''
var readonly = true
var isVodeoEnd = true
this.res = ret
ret.Nav_ListUserPaper.forEach(ele => {
if ((SOURCE_ID == '') && (ele.ANSWER == null || ele.ANSWER == 0)) {
SOURCE_ID = ele.SOURCE_ID
readonly = false
isVodeoEnd = false
}
if (SOURCE_ID.length > 0 && ele.SOURCE_ID == SOURCE_ID) {
papers.push(ele)
isOnline = ele.IS_ONLINE
if (isOnline == true && filepath == '') {
filepath = ele.FILE_PATH
}
}
});
if (SOURCE_ID == "") {
papers = ret.Nav_ListUserPaper
}
if (filepath == null || filepath == "") {
isVodeoEnd = true
}
this.papers = papers
this.isOnline = isOnline
this.readonly = readonly
this.SOURCE_ID = SOURCE_ID
this.filepath = filepath
this.filepathsWeb = config.uni_app_web_source_url + filepath
this.filepaths = filepath
if (this.filepaths.indexOf('vid') !== -1) {
this.polyvy = true
} else {
this.polyvy = false
}
const regex = /vid=([^&]+)/;
const match = this.filepaths.match(regex);
this.vid = match ? match[1] : '';
this.isVodeoEnd = isVodeoEnd
this.papers.forEach(item => {
let test = {}
if (item.Nav_Test.TYPE != 0) {
this.radiolist2[item.ID] = [];
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_A
}, {
name: item.Nav_Test.OPTION_B
})
if (item.Nav_Test.OPTION_C != undefined && item.Nav_Test.OPTION_C != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_C
})
}
if (item.Nav_Test.OPTION_D != undefined && item.Nav_Test.OPTION_D != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_D
})
}
if (item.Nav_Test.OPTION_E != undefined && item.Nav_Test.OPTION_E != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_E
})
}
}
})
}
});
},
preventFastForward(e) {
const currentTime = e.detail.currentTime;
if (currentTime > this.lastTime + 1) {
uni.$showErrorInfo('禁止快进');
const videoContext = uni.createVideoContext('myVideo', this)
videoContext.seek(this.lastTime);
} else {
this.lastTime = currentTime;
}
},
findSelectedOptions(num, OPTION_A, OPTION_B, OPTION_C, OPTION_D, OPTION_E) {
var optionVars = {
'A': {
value: 1,
variable: OPTION_A
},
'B': {
value: 2,
variable: OPTION_B
},
'C': {
value: 4,
variable: OPTION_C
},
'D': {
value: 8,
variable: OPTION_D
},
'E': {
value: 16,
variable: OPTION_E
}
};
var selectedVars = [];
for (var key in optionVars) {
if ((num & optionVars[key].value) === optionVars[key].value) {
selectedVars.push(optionVars[key].variable);
}
}
return selectedVars;
},
getType(paper) {
let ret = '';
let config = this.config;
switch (paper.Nav_Test.TYPE) {
case 0:
ret = `【是非题】(${paper.SCOREVAL}分)`;
break;
case 1:
ret = `【单选题】(${paper.SCOREVAL}分)`;
break;
case 2:
ret = `【多选题】(${paper.SCOREVAL}分)`;
break;
}
return ret;
},
doOptionChange(index, item, mask) {
if (item.Nav_Test.TYPE === 2) {
item.ANSWER |= mask;
} else {
item.ANSWER = mask;
}
if (item.ANSWER == item.Nav_Test.ANSWER) {
item.SCORE = item.SCOREVAL
} else {
item.SCORE = 0
}
},
checkboxChange(arr, item) {
let indexArr = this.findCommonElementsIndices(arr, this.radiolist2[item.ID])
item.ANSWER3 = arr;
item.ANSWER = 0;
indexArr.forEach(index => {
if (index == 0) {
item.ANSWER += 1;
} else if (index == 1) {
item.ANSWER += 2;
} else if (index == 2) {
item.ANSWER += 4;
} else if (index == 3) {
item.ANSWER += 8;
} else if (index == 4) {
item.ANSWER += 16;
} else if (index == 5) {
item.ANSWER += 32;
}
})
if (item.ANSWER == item.Nav_Test.ANSWER) {
item.SCORE = item.SCOREVAL
} else {
item.SCORE = 0
}
},
findCommonElementsIndices(arr1, arr2) {
const commonElements = [];
for (let i = 0; i < arr1.length; i++) {
for (let j = 0; j < arr2.length; j++) {
if (arr1[i] === arr2[j].name) {
commonElements.push(j);
}
}
}
return commonElements;
},
onTimeUpdate(e) {
const currentTime = e.detail.currentTime;
if (currentTime > this.lastTime + 1) {
uni.$showErrorInfo('禁止快进');
const videoContext = uni.createVideoContext('myVideo', this)
videoContext.seek(this.lastTime);
} else {
this.lastTime = currentTime;
}
},
//播放结束
onEnd() {
this.isVodeoEnd = true
},
submit() {
if (this.tableKey != 1) {
return
}
let data = JSON.parse(JSON.stringify(this.papers));
var ALLSCORE = 0
var PASSSCORE = 0
for (let i = 0; i < data.length; i++) {
if (data[i].ANSWER == 0) {
uni.$showErrorInfo(`第${i + 1}题尚未选择答题,请完成所有答题后再进行提交`)
return;
}
if (data[i].Nav_Test.TYPE === 2 && ([0, 1, 2, 4, 8].indexOf(data[i].ANSWER) !== -1)) {
uni.$showErrorInfo(`第${i + 1}题为多选题,请选择至少两个选项`)
return;
}
ALLSCORE += data[i].SCORE
if (PASSSCORE == 0) {
PASSSCORE = data[i].Nav_Source.PASSSCORE
}
}
//没过线继续考
if (ALLSCORE < PASSSCORE) {
uni.$showErrorInfo(`分数不通过,请检查后再提交(得分${ALLSCORE}通过分数为${PASSSCORE}分)`)
return false;
} else {
// 判断是静态切换 还是直接提交
let dataS = this.res;
let SOURCE_ID = this.SOURCE_ID;
if (SOURCE_ID != dataS.Nav_ListUserPaper[dataS.Nav_ListUserPaper.length - 1].SOURCE_ID) {
// 切换试题
var filepath = ''
var isOnline = false
var papers = []
var SOURCE_IDNext = ''
var readonly = true
dataS.Nav_ListUserPaper.forEach(ele => {
if ((SOURCE_IDNext == '') && (ele.ANSWER == null || ele.ANSWER == 0)) {
SOURCE_IDNext = ele.SOURCE_ID
readonly = false
}
if (SOURCE_IDNext.length > 0 && ele.SOURCE_ID == SOURCE_IDNext) {
papers.push(ele)
isOnline = ele.IS_ONLINE
if (isOnline == true && filepath == '') {
filepath = ele.FILE_PATH
}
}
});
if (filepath && filepath.length > 1) {
this.isVodeoEnd = false //继续看视频
this.filepath = filepath
this.filepathsWeb = config.uni_app_web_source_url + filepath
this.filepaths = filepath
if (this.filepaths.indexOf('vid') !== -1) {
this.polyvy = true
} else {
this.polyvy = false
}
const regex = /vid=([^&]+)/;
const match = this.filepaths.match(regex);
this.vid = match ? match[1] : '';
}
this.papers = papers
this.isOnline = isOnline
this.readonly = readonly
this.SOURCE_ID = SOURCE_IDNext
this.papers.forEach(item => {
let test = {}
if (item.Nav_Test.TYPE != 0) {
this.radiolist2[item.ID] = [];
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_A
}, {
name: item.Nav_Test.OPTION_B
})
if (item.Nav_Test.OPTION_C != undefined && item.Nav_Test.OPTION_C != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_C
})
}
if (item.Nav_Test.OPTION_D != undefined && item.Nav_Test.OPTION_D != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_D
})
}
if (item.Nav_Test.OPTION_E != undefined && item.Nav_Test.OPTION_E != "") {
this.radiolist2[item.ID].push({
name: item.Nav_Test.OPTION_E
})
}
}
})
} else {
//提交答卷
var modelR = this.res
if (this.TaskID != '')
modelR.TaskID = this.TaskID
SavePapers(modelR).then(ret => {
uni.$showMsgFunc('操作成功!', () => {
uni.navigateBack()
}, 'success', 1000)
}).catch(err => {
if (err.length > 0) {
uni.$showErrorInfo(err[0].message)
} else {
uni.$showErrorInfo('校验失败!')
}
})
}
}
},
}
}
</script>
<style scoped>
@import url("../../../../style/css/newTemplate.css");
.wrap {
flex: 1;
height: 100%;
/* 关键width 包含 padding 和 border */
padding-bottom: 80px;
position: relative;
background: #edf1fd;
}
.bottom-button-new {
position: absolute;
/* 绝对定位覆盖播放器 */
left: 0;
right: 0;
bottom: 0;
/* 靠底部显示 */
padding: 20rpx 30rpx;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
/* 渐变背景提升可读性 */
z-index: 10;
}
.scrollable-content {
height: 300px;
/* 根据实际需求设置高度 */
overflow-y: auto;
/* 垂直方向滚动 */
overflow-x: hidden;
/* 隐藏水平滚动条 */
}
.title {
height: 140rpx;
}
.player {
height: 200px;
position: relative;
overflow: hidden;
}
.vod-player {
flex: 1;
}
.controls-contain {
position: relative;
height: 60px;
background-color: #000;
}
/* 悬浮控件层 */
.floating-controls {
position: absolute;
/* 绝对定位覆盖播放器 */
left: 0;
right: 0;
bottom: 0;
height: 60px;
z-index: 10;
}
.abs-box {
display: flex;
flex-direction: column;
justify-content: space-between;
/* align-items: center; */
flex: 1;
/* background-color: aliceblue; */
padding: 5px 10px;
/* width: 100%; */
/* background-color: aqua; */
/* box-sizing: border-box; */
}
.playing-icon {
/* width: 50px; */
/* margin-top: 5px; */
margin-right: 40px;
margin-left: 40px;
/* height: 40px; */
}
/* 进度条容器 */
.progress-container {
/* width: 100%; */
height: 30px;
/* margin-top: 20rpx; */
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
/* box-sizing: border-box; */
}
/* 时间文本 */
.time-text {
color: #fff;
font-size: 24px;
/* margin-bottom: 10rpx; */
display: flex;
margin: 0px 5px;
justify-content: space-between;
/* margin-left: 10px; */
/* width: 80px; */
}
/* 进度条背景 */
.progress-bar {
/* height: 20px; */
/* width: 100%; */
flex: 1;
/* background: rgba(255, 255, 255, 0.3); */
border-radius: 4rpx;
}
.progress-content {
display: flex;
/* width: 100%; */
height: 100%;
flex: 1;
background-color: aqua;
position: relative;
/* cursor: pointer; */
overflow: hidden;
}
</style>