duidui_mini_program/pages/camp_detail/modules/task-handler.js
2026-03-27 10:41:46 +08:00

566 lines
18 KiB
JavaScript
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.

/**
* 任务处理模块
* 负责所有任务相关的处理逻辑
*/
import { campApi } from '../../../config/camp_api.js';
import { questionApi } from '../../../config/question_api.js';
import * as videoController from './video-controller.js';
/**
* 处理任务点击
* @param {Object} context - 页面上下文
* @param {Object} e - 事件对象
*/
export function handleTaskClick(context, e) {
var that = context;
// 修改已发送标记
that.setData({
hasVideoPlayed: false,
isAutoPlay: true,
hasLogged10Percent: false
});
var taskId = e.currentTarget.dataset.taskId;
var sectionId = e.currentTarget.dataset.sectionId;
var number = e.currentTarget.dataset.number;
var courseList = context.data.courseList;
var hasJoined = context.data.hasJoined;
var currentSection = context.data.currentSection; // 使用维护的当前小节信息
// 展示等待
wx.showLoading({
title: '请稍等...',
});
// 查找点击的小节
var clickedCourse = null;
var targetId = sectionId;
if (courseList && courseList.length > 0) {
// 优先通过 ID 匹配
if (targetId) {
clickedCourse = courseList.find(function (t) {
return (
String(t.id) === String(targetId) ||
String(t.course_id) === String(targetId) ||
String(t.section_id) === String(targetId)
);
});
}
// 如果通过 ID 找不到,再通过 section_number 匹配
if (!clickedCourse && number !== undefined && number !== null) {
clickedCourse = courseList.find(function (t) {
var tNumber = t.section_number || t.number;
return tNumber === number;
});
}
}
if (!clickedCourse) {
wx.hideLoading();
wx.showToast({
title: '未找到对应小节',
icon: 'none'
});
return;
}
var actualSectionId = clickedCourse.id || clickedCourse.course_id || clickedCourse.section_id || targetId;
// 时间间隔未到:若该小节在 sectionUnlockAtMap 中(有解锁倒计时),则禁止进入并提示
var sectionUnlockAtMap = context.data.sectionUnlockAtMap || {};
if (sectionUnlockAtMap[actualSectionId]) {
var unlockAt = sectionUnlockAtMap[actualSectionId];
var nowSec = Math.floor(Date.now() / 1000);
var left = unlockAt - nowSec;
var msg = '时间到了才能开启';
if (left > 0) {
// 自然天(明日解锁):不显示具体倒计时
var unlockDate = new Date(unlockAt * 1000);
var today = new Date();
var tomorrowStart = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1, 0, 0, 0, 0);
var tomorrowEnd = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2, 0, 0, 0, 0) - 1;
if (unlockDate.getTime() >= tomorrowStart.getTime() && unlockDate.getTime() < tomorrowEnd) {
msg = '任务将于明日才能开启';
} else {
var h = Math.floor(left / 3600);
var m = Math.floor((left % 3600) / 60);
if (h > 0) {
msg = '时间到了才能开启,该小节将在 ' + h + ' 小时 ' + m + ' 分钟后解锁';
} else if (m > 0) {
msg = '时间到了才能开启,该小节将在 ' + m + ' 分钟后解锁';
} else {
msg = '时间到了才能开启,请稍候';
}
}
}
wx.hideLoading();
wx.showToast({ title: msg, icon: 'none', duration: 2500 });
return;
}
// 检查打卡营是否开启
if (!hasJoined) {
wx.showModal({
title: '提示',
content: '确认开启打卡营😘?',
complete: function (res) {
if (res.confirm) {
if (context.toggleCardType) {
context.toggleCardType();
}
}
}
});
wx.hideLoading();
return;
}
// 验证1是否检查上一小节仅看后台配置 require_previous_section默认 1、2、3 都可直接做,不按 section_number 推断)
var needCheckPrevious = !!(clickedCourse.require_previous_section === true);
// 如果不需要检查上一小节,跳过;否则按下面逻辑验证
if (needCheckPrevious) {
var prevCourse = null;
var currentIndex = courseList.findIndex(function (t) {
return t === clickedCourse;
});
if (currentIndex > 0) {
prevCourse = courseList[currentIndex - 1];
} else {
var clickedSectionNumber = clickedCourse.section_number || clickedCourse.number || 0;
var prevSectionNumber = clickedSectionNumber - 1;
prevCourse = courseList.find(function (t) {
var tSectionNumber = t.section_number || t.number || 0;
return tSectionNumber === prevSectionNumber;
});
}
if (!prevCourse) {
wx.hideLoading();
wx.showToast({
title: '数据异常,无法找到上一小节',
icon: 'error'
});
return;
}
if (!prevCourse.is_completed) {
var prevSectionTitle = prevCourse.title || prevCourse.course_title || '上一小节';
wx.hideLoading();
wx.showModal({
title: '提示',
content: '请先完成上一小节\n👇👇👇\n《' + prevSectionTitle + '》',
showCancel: false,
confirmText: '知道了'
});
return;
}
}
// 当前小节开启则进行前置任务判断
if (clickedCourse.is_started) {
that.setData({
currentSelectedTaskId: taskId,
});
// 验证2判断是否有前置任务未完成
var prerequisites = e.currentTarget.dataset.task.prerequisites;
var isCompleted = true;
var taskTitle = '';
if (prerequisites && prerequisites.length > 0) {
prerequisites.forEach(function (item) {
var course = that.data.courseList.find(function (t) {
return String(t.course_id) === String(actualSectionId) ||
String(t.id) === String(actualSectionId) ||
String(t.section_id) === String(actualSectionId);
});
if (!course || !course.tasks) return;
course.tasks.forEach(function (task) {
var taskId = task.id || task.task_id;
if (taskId && (String(taskId) === String(item) || parseInt(taskId) === parseInt(item))) {
if (task.status !== 'Completed') {
isCompleted = false;
taskTitle = task.task_title || task.title || '前置任务';
}
}
});
});
}
if (!isCompleted) {
wx.hideLoading();
wx.showModal({
title: '提示',
content: '请先完成前置任务\n👇👇👇\n《' + taskTitle + '》',
showCancel: false,
confirmText: '知道了'
});
return;
}
// 处理任务跳转
that.navigateToTaskPage(e);
return;
} else {
// 当前小节未开启:需要先开启小节
// 如果上一小节验证通过(或不需要验证),则进入开启流程
// 通过 navigateToTaskPage 中的 checkAndUnlockSection 来处理
that.navigateToTaskPage(e);
return;
}
}
/**
* 导航到任务页面
* @param {Object} context - 页面上下文
* @param {Object} e - 事件对象
*/
export function navigateToTaskPage(context, e) {
// 注意:这里不暂停视频,因为如果是视频任务需要自动播放
// 暂停逻辑会在 executeTaskNavigation 中根据任务类型处理
var campId = context.data.campId;
var sectionId = e.currentTarget.dataset.sectionId || context.data.currentSelectedCourseId;
var taskId = e.currentTarget.dataset.taskId;
var taskType = e.currentTarget.dataset.type;
var taskData = e.currentTarget.dataset.task || {};
var taskTitle = e.currentTarget.dataset.taskTitle || taskData.title || taskData.task_title || '';
var taskStatus = taskData.status || (e.currentTarget.dataset.task && e.currentTarget.dataset.task.status);
var taskDetail = taskData.detail || (e.currentTarget.dataset.task && e.currentTarget.dataset.task.detail);
// 检查小节是否在访问列表中,如果不在则尝试开启
if (sectionId) {
if (context.checkAndUnlockSection) {
context.checkAndUnlockSection(sectionId, function (hasAccess) {
if (!hasAccess) {
return;
}
executeTaskNavigation(context, campId, sectionId, taskId, taskType, taskData, taskTitle, taskStatus, taskDetail);
}, true);
} else {
executeTaskNavigation(context, campId, sectionId, taskId, taskType, taskData, taskTitle, taskStatus, taskDetail);
}
} else {
executeTaskNavigation(context, campId, sectionId, taskId, taskType, taskData, taskTitle, taskStatus, taskDetail);
}
}
/**
* 执行任务跳转逻辑
* @param {Object} context - 页面上下文
* @param {String} campId - 打卡营ID
* @param {String} sectionId - 小节ID
* @param {String} taskId - 任务ID
* @param {String} taskType - 任务类型
* @param {Object} taskData - 任务数据
* @param {String} taskTitle - 任务标题
* @param {String} taskStatus - 任务状态
* @param {Object} taskDetail - 任务详情
*/
export function executeTaskNavigation(context, campId, sectionId, taskId, taskType, taskData, taskTitle, taskStatus, taskDetail) {
var sendParams = {
campId: String(campId),
sectionId: sectionId,
courseId: sectionId,
taskId: taskId,
taskType: taskType,
taskTitle: taskTitle,
taskStatus: taskStatus,
taskDetail: taskDetail,
task: taskData
};
// 规范化任务类型
var normalizedTaskType = (taskType || '').toString().trim().toUpperCase();
if (!normalizedTaskType && taskData) {
var rawType = taskData.task_type || taskData.type;
if (rawType) {
normalizedTaskType = String(rawType).trim().toUpperCase();
}
}
// 如果还是没有识别出类型,尝试通过 content 判断
if (!normalizedTaskType && taskData) {
var content = taskData.content || {};
// 如果有 essay 相关字段,判断为申论题
if (content.essay || (content.essay_question && content.essay_question.exam_id)) {
normalizedTaskType = 'ESSAY';
}
// 如果有 exam_id 或 paper_id判断为客观题
else if (content.exam_id || content.paper_id || (content.objective && content.objective.exam_id)) {
normalizedTaskType = 'OBJECTIVE';
}
// 如果有 video_url判断为视频任务
else if (content.video_url || (content.video && content.video.video_url)) {
normalizedTaskType = 'VIDEO';
}
// 如果有 image_text 相关字段,判断为图文任务
else if (content.image_text || (content.image_text && content.image_text.image_url)) {
normalizedTaskType = 'IMAGE_TEXT';
}
// 如果有 pdf_url 或 description判断为主观题
else if (content.pdf_url || content.description || (content.subjective && (content.subjective.pdf_url || content.subjective.description))) {
normalizedTaskType = 'SUBJECTIVE';
}
}
console.log('任务类型判断 - taskType:', taskType, 'taskData.task_type:', taskData?.task_type, 'normalizedTaskType:', normalizedTaskType, 'taskData:', taskData);
// 根据任务类型处理
switch (normalizedTaskType) {
case 'VIDEO':
// 视频任务:自动播放
if (context.handleVideoTask) {
context.handleVideoTask(sendParams);
} else {
videoController.handleVideoTask(context, sendParams);
}
break;
case 'IMAGE_TEXT':
// 非视频任务:暂停并隐藏视频
videoController.pauseAndHideVideo(context);
handleTextImageTask(context, sendParams);
break;
case 'OBJECTIVE':
// 非视频任务:暂停并隐藏视频
videoController.pauseAndHideVideo(context);
handleObjectiveTask(context, sendParams);
break;
case 'SUBJECTIVE':
// 非视频任务:暂停并隐藏视频
videoController.pauseAndHideVideo(context);
handleSubjectiveTask(context, sendParams);
break;
case 'ESSAY':
// 非视频任务:暂停并隐藏视频
videoController.pauseAndHideVideo(context);
handleEssayTask(context, sendParams);
break;
default:
// 非视频任务:暂停并隐藏视频
videoController.pauseAndHideVideo(context);
console.warn('未知任务类型:', normalizedTaskType, 'taskData:', taskData);
wx.showToast({
title: '暂不支持该类型任务: ' + (normalizedTaskType || '未知'),
icon: 'none',
duration: 3000
});
}
wx.hideLoading();
}
/**
* 处理客观题任务
* @param {Object} context - 页面上下文
* @param {Object} sendParams - 任务参数
*/
export function handleObjectiveTask(context, sendParams) {
console.log('handleObjectiveTask 被调用sendParams:', sendParams);
campApi.getTaskDetailById(sendParams.taskId)
.then(function (res) {
console.log('getTaskDetailById 返回:', res);
var paperId = null;
var task = (res && res.task) || (res && res.data && res.data.task);
if (res && (res.success === true || res.code === 200) && task) {
var content = task.content || {};
paperId = content.exam_id || content.paper_id ||
(content.objective && (content.objective.exam_id || content.objective.paper_id)) || null;
}
if (!paperId) {
wx.showToast({ title: '试卷ID不存在', icon: 'none' });
return;
}
var userId = wx.getStorageSync('wxuserid');
if (!userId) {
wx.showToast({
title: '请先登录',
icon: 'none'
});
return;
}
// 请求答题记录接口(用于判断跳转答题页还是结果页)
console.log('请求答题记录 getAnswerRecord:', { userId: userId, paperId: paperId });
return questionApi.getAnswerRecord(userId, paperId, 1, 361)
.then(function(recordRes) {
var hasRecord = (recordRes.success === true && recordRes.records && recordRes.records.length > 0) ||
(recordRes.code === 200 && recordRes.data && recordRes.data.length > 0) ||
(recordRes.data && Array.isArray(recordRes.data) && recordRes.data.length > 0) ||
(recordRes.records && Array.isArray(recordRes.records) && recordRes.records.length > 0);
var query = [];
query.push('paper_id=' + encodeURIComponent(paperId));
query.push('task_id=' + encodeURIComponent(sendParams.taskId));
query.push('camp_id=' + encodeURIComponent(sendParams.campId));
var title = sendParams.taskTitle || '客观题';
query.push('task_title=' + encodeURIComponent(title));
if (sendParams.sectionId !== undefined && sendParams.sectionId !== null && sendParams.sectionId !== 'undefined') {
query.push('course_id=' + encodeURIComponent(sendParams.sectionId));
}
if (hasRecord) {
// 如果有答题记录,跳转到结果页面
wx.navigateTo({
url: `/pages/camp_task_objective_questions_result/index?${query.join('&')}`,
success: function() {
console.log('跳转到结果页面成功');
},
fail: function(err) {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败: ' + (err.errMsg || '未知错误'),
icon: 'none',
duration: 3000
});
}
});
} else {
// 如果没有答题记录,跳转到答题页面
wx.navigateTo({
url: `/pages/camp_task_objective_questions/index?${query.join('&')}`,
success: function() {
console.log('跳转到答题页面成功');
},
fail: function(err) {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败: ' + (err.errMsg || '未知错误'),
icon: 'none',
duration: 3000
});
}
});
}
})
.catch(function(error) {
console.error('获取答题记录失败:', error);
var query = [];
query.push('paper_id=' + encodeURIComponent(paperId));
query.push('task_id=' + encodeURIComponent(sendParams.taskId));
query.push('camp_id=' + encodeURIComponent(sendParams.campId));
var title = sendParams.taskTitle || '客观题';
query.push('task_title=' + encodeURIComponent(title));
if (sendParams.sectionId !== undefined && sendParams.sectionId !== null && sendParams.sectionId !== 'undefined') {
query.push('course_id=' + encodeURIComponent(sendParams.sectionId));
}
// 获取答题记录失败,直接跳转到答题页面
wx.navigateTo({
url: `/pages/camp_task_objective_questions/index?${query.join('&')}`,
success: function() {
console.log('跳转到答题页面成功');
},
fail: function(err) {
console.error('跳转失败:', err);
wx.showToast({
title: '跳转失败: ' + (err.errMsg || '未知错误'),
icon: 'none',
duration: 3000
});
}
});
});
})
.catch(function (err) {
console.error('getTaskDetailById 或 getAnswerRecord 失败:', err);
wx.showToast({ title: '获取任务信息失败', icon: 'none' });
});
}
/**
* 处理主观题任务
* @param {Object} context - 页面上下文
* @param {Object} sendParams - 任务参数
*/
export function handleSubjectiveTask(context, sendParams) {
var query = [];
query.push('campId=' + encodeURIComponent(sendParams.campId || ''));
query.push('taskId=' + encodeURIComponent(sendParams.taskId || ''));
var title = sendParams.taskTitle || '主观题';
query.push('taskTitle=' + encodeURIComponent(title));
if (sendParams.sectionId !== undefined && sendParams.sectionId !== null && sendParams.sectionId !== 'undefined') {
query.push('courseId=' + encodeURIComponent(sendParams.sectionId || sendParams.courseId || ''));
}
wx.navigateTo({
url: '/pages/camp_task_subjective_question/index?' + query.join('&')
});
}
/**
* 处理图文任务
* @param {Object} context - 页面上下文
* @param {Object} sendParams - 任务参数
*/
export function handleTextImageTask(context, sendParams) {
wx.navigateTo({
url: '/pages/camp_task_text_image/index?task_id=' + sendParams.taskId + '&task_title=' + sendParams.taskTitle + '&course_id=' + sendParams.sectionId + '&camp_id=' + sendParams.campId + '&task_status=' + sendParams.taskStatus
});
}
/**
* 处理申论题任务
* @param {Object} context - 页面上下文
* @param {Object} sendParams - 任务参数
*/
export function handleEssayTask(context, sendParams) {
campApi.getTaskDetailById(sendParams.taskId).then(function (res) {
if (!res || res.success !== true || !res.task) {
wx.showToast({
title: '获取申论题信息失败',
icon: 'none'
});
return;
}
var taskInfo = res.task;
if (!taskInfo) {
wx.showToast({
title: '任务数据异常',
icon: 'none'
});
return;
}
// 兼容多种字段结构获取 paperId
var paperId = null;
var content = taskInfo.content || {};
if (content) {
if (content.essay) {
paperId = content.essay.paper_id || content.essay.exam_id || null;
}
if (!paperId) {
paperId = content.paper_id || content.exam_id || null;
}
}
if (!paperId) {
paperId = taskInfo.paper_id || taskInfo.exam_id || null;
}
if (!paperId) {
wx.showToast({
title: '试卷ID不存在',
icon: 'none'
});
return;
}
sendParams.paperId = paperId;
wx.navigateTo({
url: '/pages/camp_task_essay_question/index',
events: {
onDataFromChild: function (data) {
},
onParamsReceived: function (params) {
}
},
success: function (res) {
res.eventChannel.emit('sendParams', sendParams);
}
});
});
}