Merge remote-tracking branch 'origin/main'

This commit is contained in:
=
2025-09-18 08:40:17 +08:00
59 changed files with 3697 additions and 4029 deletions
@@ -42,18 +42,18 @@ layout("/layouts/platform_h5.html"){
<div v-else-if="videoInfo" class="video-player">
<video
ref="videoElement"
class="video-element"
:src="videoInfo.url"
controls
preload="metadata"
@loadedmetadata="onVideoLoaded"
@canplay="onVideoCanPlay"
@play="onVideoPlay"
@pause="onVideoPause"
@timeupdate="onTimeUpdate"
@ended="onVideoEnded"
@error="onVideoError"
ref="videoElement"
class="video-element"
:src="videoSrc"
controls
preload="metadata"
@loadedmetadata="onVideoLoaded"
@canplay="onVideoCanPlay"
@play="onVideoPlay"
@pause="onVideoPause"
@timeupdate="onTimeUpdate"
@ended="onVideoEnded"
@error="onVideoError"
>
您的浏览器不支持视频播放
</video>
@@ -63,227 +63,241 @@ layout("/layouts/platform_h5.html"){
</div>
<!-- 进度保存提示 -->
<van-toast v-model="showProgressToast" message="进度已保存" :duration="1000" />
<van-toast v-model="showProgressToast" message="进度已保存" :duration="1000"/>
<!-- 完成学习弹窗 -->
<van-dialog
v-model="showCompletionDialog"
title="恭喜完成学习!"
message="您已完成本视频的学习,学习记录已保存。"
show-cancel-button
cancel-button-text="继续观看"
confirm-button-text="返回课程"
@confirm="backToCourse"
v-model="showCompletionDialog"
title="恭喜完成学习!"
message="您已完成本视频的学习,学习记录已保存。"
show-cancel-button
cancel-button-text="继续观看"
confirm-button-text="返回课程"
@confirm="backToCourse"
></van-dialog>
</div>
<script>
const vue = new Vue({
el: "#app",
store,
data() {
return {
videoInfo: null,
loading: true,
videoId: null,
courseId: null,
videoTitle: '视频播放',
isPlaying: false,
progressSaveTimer: null,
showProgressToast: false,
showCompletionDialog: false,
savedProgress: 0
}
},
methods: {
pageBack(){
this.historyBack(this.clearProgressSave)
const vue = new Vue({
el: "#app",
store,
data() {
return {
videoInfo: null,
loading: true,
videoId: null,
courseId: null,
videoTitle: '视频播放',
isPlaying: false,
progressSaveTimer: null,
showProgressToast: false,
showCompletionDialog: false,
savedProgress: 0,
progressSet: false // 标记进度是否已设置,避免死循环
}
},
// 加载视频信息
async loadVideoInfo() {
if (!this.videoId) {
this.$toast.fail('缺少视频ID参数');
this.loading = false;
return;
computed: {
videoSrc() {
if (this.videoInfo && this.videoInfo.url) {
const id = this.videoInfo.url.split('id=')[1];
console.log('/platform/sys/file/videoPlay?id=' + id)
return '/platform/sys/file/videoPlay?id=' + id;
}
return null
}
},
try {
const { code, data, msg } = await this.$axios.post('/platform/h5/edu/video/detail', {
videoId: this.videoId
});
methods: {
pageBack() {
this.historyBack(this.clearProgressSave)
},
if (code === 0 && data) {
this.videoInfo = data;
this.$nextTick(() => {
this.loadWatchProgress();
// 加载视频信息
async loadVideoInfo() {
if (!this.videoId) {
this.$toast.fail('缺少视频ID参数');
this.loading = false;
return;
}
try {
const {code, data, msg} = await this.$axios.post('/platform/h5/edu/video/detail', {
videoId: this.videoId
});
} else {
this.$toast.fail(msg || '加载视频信息失败');
if (code === 0 && data) {
this.videoInfo = data;
this.$nextTick(() => {
this.loadWatchProgress();
});
} else {
this.$toast.fail(msg || '加载视频信息失败');
}
} catch (error) {
this.$toast.fail('网络错误');
}
} catch (error) {
this.$toast.fail('网络错误');
}
this.loading = false;
},
this.loading = false;
},
// 视频加载完成
onVideoLoaded() {
console.log('视频元数据加载完成');
},
// 视频加载完成
onVideoLoaded() {
console.log('视频元数据加载完成');
},
// 视频可以播放
onVideoCanPlay() {
console.log('视频可以播放');
// 视频可以播放时,设置观看进度
this.setWatchProgress();
},
// 视频可以播放
onVideoCanPlay() {
console.log('视频可以播放');
// 视频可以播放时,设置观看进度
this.setWatchProgress();
},
// 视频开始播放
onVideoPlay() {
this.isPlaying = true;
this.startProgressSave();
},
// 视频开始播放
onVideoPlay() {
this.isPlaying = true;
this.startProgressSave();
},
// 视频暂停
onVideoPause() {
this.isPlaying = false;
this.saveProgress();
},
// 时间更新
onTimeUpdate() {
console.log('时间更新')
// 可以在这里添加进度更新逻辑
},
// 视频播放结束
onVideoEnded() {
this.isPlaying = false;
this.markVideoCompleted();
},
// 视频加载错误
onVideoError() {
this.$toast.fail('视频加载失败');
},
// 加载观看进度
async loadWatchProgress() {
if (!this.videoId || !this.courseId) return;
try {
const { code, data } = await this.$axios.post('/platform/h5/edu/study/record', {
videoId: this.videoId
});
if (code === 0 && data && data.watchedDuration > 0) {
this.savedProgress = data.watchedDuration;
}
} catch (error) {
console.error('加载观看进度失败:', error);
}
},
// 设置观看进度
setWatchProgress() {
if (this.savedProgress > 0) {
const video = this.$refs.videoElement;
if (video && video.readyState >= 3) {
// 使用setTimeout确保DOM更新完成
setTimeout(() => {
try {
video.currentTime = this.savedProgress;
console.log('设置观看进度成功:', this.savedProgress);
} catch (error) {
console.error('设置观看进度失败:', error);
}
}, 100);
} else {
console.log('视频还未准备好,readyState:', video ? video.readyState : 'video不存在');
}
}
},
// 保存观看进度
async saveProgress() {
const video = this.$refs.videoElement;
if (!video || !this.videoId || !this.courseId) return;
try {
await $.post('/platform/h5/edu/study/progress/save', {
videoId: this.videoId,
courseId: this.courseId,
watchedDuration: Math.floor(video.currentTime)
});
this.showProgressToast = true;
} catch (error) {
console.error('保存进度失败:', error);
}
},
// 开始定时保存进度
startProgressSave() {
this.clearProgressSave();
this.progressSaveTimer = setInterval(() => {
// 视频暂停
onVideoPause() {
this.isPlaying = false;
this.saveProgress();
}, 10000); // 每10秒保存一次
},
},
// 清除定时保存
clearProgressSave() {
if (this.progressSaveTimer) {
clearInterval(this.progressSaveTimer);
this.progressSaveTimer = null;
}
},
// 时间更新
onTimeUpdate() {
console.log('时间更新')
// 可以在这里添加进度更新逻辑
},
// 标记视频完成
async markVideoCompleted() {
if (!this.videoId || !this.courseId) return;
// 视频播放结束
onVideoEnded() {
this.isPlaying = false;
this.markVideoCompleted();
},
try {
const { code } = await $.post('/platform/h5/edu/study/complete', {
videoId: this.videoId,
courseId: this.courseId
});
// 视频加载错误
onVideoError() {
this.$toast.fail('视频加载失败');
},
if (code === 0) {
this.showCompletionDialog = true;
// 加载观看进度
async loadWatchProgress() {
if (!this.videoId || !this.courseId) return;
try {
const {code, data} = await this.$axios.post('/platform/h5/edu/study/record', {
videoId: this.videoId
});
if (code === 0 && data && data.watchedDuration > 0) {
this.savedProgress = data.watchedDuration;
}
} catch (error) {
console.error('加载观看进度失败:', error);
}
},
// 设置观看进度
setWatchProgress() {
if (this.savedProgress > 0 && !this.progressSet) {
const video = this.$refs.videoElement;
if (video && video.readyState >= 3) {
// 使用setTimeout确保DOM更新完成
setTimeout(() => {
try {
this.progressSet = true; // 标记进度已设置,避免重复设置
video.currentTime = this.savedProgress;
console.log('设置观看进度成功:', this.savedProgress);
} catch (error) {
console.error('设置观看进度失败:', error);
}
}, 100);
} else {
console.log('视频还未准备好,readyState:', video ? video.readyState : 'video不存在');
}
}
},
// 保存观看进度
async saveProgress() {
const video = this.$refs.videoElement;
if (!video || !this.videoId || !this.courseId) return;
try {
await $.post('/platform/h5/edu/study/progress/save', {
videoId: this.videoId,
courseId: this.courseId,
watchedDuration: Math.floor(video.currentTime)
});
this.showProgressToast = true;
} catch (error) {
console.error('保存进度失败:', error);
}
},
// 开始定时保存进度
startProgressSave() {
this.clearProgressSave();
this.progressSaveTimer = setInterval(() => {
this.saveProgress();
}, 10000); // 每10秒保存一次
},
// 清除定时保存
clearProgressSave() {
if (this.progressSaveTimer) {
clearInterval(this.progressSaveTimer);
this.progressSaveTimer = null;
}
},
// 标记视频完成
async markVideoCompleted() {
if (!this.videoId || !this.courseId) return;
try {
const {code} = await $.post('/platform/h5/edu/study/complete', {
videoId: this.videoId,
courseId: this.courseId
});
if (code === 0) {
this.showCompletionDialog = true;
}
} catch (error) {
console.error('标记完成失败:', error);
}
},
// 返回课程
backToCourse() {
if (this.courseId) {
} else {
this.historyBack();
}
} catch (error) {
console.error('标记完成失败:', error);
}
},
// 返回课程
backToCourse() {
if (this.courseId) {
mounted() {
// 获取URL参数
const urlParams = new URLSearchParams(window.location.search);
this.videoId = urlParams.get('videoId');
this.courseId = urlParams.get('courseId');
this.videoTitle = decodeURIComponent(urlParams.get('title') || '视频播放');
} else {
this.historyBack();
}
this.loadVideoInfo();
},
beforeDestroy() {
// 页面销毁前保存进度
this.saveProgress();
this.clearProgressSave();
}
},
mounted() {
// 获取URL参数
const urlParams = new URLSearchParams(window.location.search);
this.videoId = urlParams.get('videoId');
this.courseId = urlParams.get('courseId');
this.videoTitle = decodeURIComponent(urlParams.get('title') || '视频播放');
this.loadVideoInfo();
},
beforeDestroy() {
// 页面销毁前保存进度
this.saveProgress();
this.clearProgressSave();
}
});
});
</script>
<!--#
@@ -156,7 +156,7 @@ layout("/layouts/platform_h5.html"){
if (this.timerInterval) {
clearInterval(this.timerInterval)
}
pjaxReplace('platform/h5/qsv')
historyBack()
},
//答题计时器
@@ -27,8 +27,8 @@ const SUGGESTION_BOX_INFO = {
</van-cell>
<van-cell title="办理时间">{{ task.finishTime }}</van-cell>
<van-cell title="办理结果">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="task.ext.caseFilingResult"></dict-tag>
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</van-cell>
<van-cell title="办理意见" v-if="!task.ext.isFirstTaskNode" class="direction-column-cell">
<div v-html="task.taskFormData.tf_opinion"></div>
@@ -20,7 +20,7 @@ layout("/layouts/platform_h5.html"){
<template v-slot="{index,row}">
<table-column label="申请人">{{row.userName}}</table-column>
<table-column label="申请时间">{{row.submitTime}}</table-column>
<table-column label="当前节点">{{row.curTaskName}}</table-column>
<table-column label="当前节点">{{row.taskName}}</table-column>
</template>
<template #actions="{index,row}">
<div class="action-btn" @click="onView(row)">
@@ -91,7 +91,7 @@ layout("/layouts/platform_h5.html"){
// 编辑
onEdit(row) {
this.$pjaxReplace("/platform/h5/suggestionBox/write?bizId=" + row.id + "&taskId=" + row.startTaskId)
this.$pjaxReplace("/platform/suggestionBox/write/h5?bizId=" + row.id + "&taskId=" + (row.startTaskId || ''))
},
// 撤回
@@ -73,7 +73,7 @@ layout("/layouts/platform_h5.html"){
this.$axios.post('/platform/suggestionBox/write/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$toast.success("保存成功");
pjaxReplace("/platform/h5/suggestionBox/mine")
pjaxReplace("/platform/suggestionBox/mine/h5")
}
})
}).catch(() => {
@@ -96,7 +96,7 @@ layout("/layouts/platform_h5.html"){
this.$axios.post('/platform/suggestionBox/write/submit', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$toast.success("提交成功");
pjaxReplace("/platform/h5/suggestionBox/mine")
pjaxReplace("/platform/suggestionBox/mine/h5")
}
})
}).catch(() => {
@@ -265,6 +265,11 @@ const apps = {
// 显示应用菜单弹框
showAppMenus(app, menus) {
if(app.href && menus.length === 0){
this.$pjaxReplace(app.href)
return;
}
if (!menus || menus.length === 0) {
this.$toast('该应用暂无可用功能')
return
@@ -92,7 +92,7 @@ const todo = {
</div>
<div v-else class="empty-section">
<van-empty :description="getEmptyText()"/>
<van-empty :description="getEmptyText()"></van-empty>
</div>
</van-list>
</van-pull-refresh>