/** * 任务处理模块 * 负责所有任务相关的处理逻辑 */ 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); } }); }); }