You need to enable JavaScript to run this app. 如何在.NET Core中用jQuery实现动态多题型章节评估的校验与跳转
优惠活动
大模型
产品
解决方案
定价
更多

如何在.NET Core中用jQuery实现动态多题型章节评估的校验与跳转

四类题型适配的章节评估校验与跳转实现方案

现有代码的核心问题

  • 仅覆盖radio类型的选中状态判断,完全未纳入多选checkbox、下拉排序题的作答收集与校验逻辑
  • 未内置作答与标准答案的比对流程,仅将选中值存入数组无实际校验作用
  • 依赖parent().parent()的固定层级遍历定位表单容器,动态生成DOM时只要结构微调就会定位错误,直接导致跳转失效
  • 未区分多选(无序匹配)、排序题(有序匹配)的校验规则,容易出现判分逻辑错误
  • 绑定方式为直接给元素加click事件,动态插入的DOM元素无法触发事件,是之前fieldset方案在动态场景失效的核心原因

分步实现方案

1. 统一DOM锚点规则(解决动态定位失效问题)

摒弃对固定嵌套层级的依赖,给动态生成的元素加上统一的标识属性,不管内部结构怎么调整都能准确定位:

  • 每个章节外层容器统一添加class="quiz-chapter"属性,同时在标签上直接存当前章节的标准答案:data-correct-answer='{"q1":"A","q2":["A","C"],"q3":"true","q4":["item2","item1","item3"]}'
  • 不同题型的输入控件添加data-question-type标识,区分single(单选)、multi(多选)、judge(判断)、sort(排序)
  • 跳转按钮统一保留原有类名next/back,不做额外类名调整

2. 通用作答收集函数

针对四类题型的输入特性,统一收集当前章节内的所有用户作答,不需要为每类题型单独写收集逻辑:

function collectChapterAnswers($chapterEl) {
  const userAnswers = {};
  // 收集单选、判断题(radio类)
  $chapterEl.find('input[type="radio"]:checked').each(function() {
    const qId = $(this).data('question-id');
    userAnswers[qId] = $(this).val();
  });
  // 收集多选题(checkbox类)
  $chapterEl.find('input[type="checkbox"]').each(function() {
    const qId = $(this).data('question-id');
    if (!userAnswers[qId]) userAnswers[qId] = [];
    if ($(this).is(':checked')) userAnswers[qId].push($(this).val());
  });
  // 收集排序题(下拉选择类),按页面上下拉的先后顺序拼接排序结果
  $chapterEl.find('select[data-question-type="sort"]').each(function() {
    const qId = $(this).data('question-id');
    const sortResult = [];
    $chapterEl.find(`select[data-question-id="${qId}"]`).each(function() {
      sortResult.push($(this).val());
    });
    userAnswers[qId] = sortResult;
  });
  return userAnswers;
}

3. 分层校验逻辑

先校验作答完整性(漏答拦截),再校验作答正确性(答错拦截),最后才允许跳转:

function validateCurrentChapter($chapterEl, userAnswers) {
  const correctAnswers = JSON.parse($chapterEl.attr('data-correct-answer'));
  // 第一层:漏答检查
  for (const qId of Object.keys(correctAnswers)) {
    if (userAnswers[qId] === undefined || (Array.isArray(userAnswers[qId]) && userAnswers[qId].length === 0)) {
      return {
        passed: false,
        tip: '请完成当前章节的所有题目后再跳转'
      }
    }
  }
  // 第二层:正确性比对
  for (const qId of Object.keys(correctAnswers)) {
    const standardVal = correctAnswers[qId];
    const userVal = userAnswers[qId];
    const qType = $chapterEl.find(`[data-question-id="${qId}"]`).first().data('question-type');
    // 单选、判断题:值严格匹配即可
    if (!Array.isArray(standardVal)) {
      if (String(userVal) !== String(standardVal)) {
        return {
          passed: false,
          tip: '当前章节有题目作答错误,请核对后再尝试跳转'
        }
      }
    }
    // 多选题:转换为无序列表匹配,不要求选项顺序一致
    if (qType === 'multi') {
      const standardSet = [...standardVal].sort().join(',');
      const userSet = [...userVal].sort().join(',');
      if (standardSet !== userSet) {
        return {
          passed: false,
          tip: '当前多选题作答错误,请核对选项后再尝试跳转'
        }
      }
    }
    // 排序题:严格按顺序匹配,不打乱数组比对
    if (qType === 'sort') {
      if (standardVal.join(',') !== userVal.join(',')) {
        return {
          passed: false,
          tip: '当前排序题顺序错误,请调整排序结果后再尝试跳转'
        }
      }
    }
  }
  return { passed: true, tip: '作答正确,已解锁下一章节' };
}

4. 绑定跳转事件(适配动态生成场景)

用全局事件委托绑定点击事件,不管章节是静态写的还是后续动态生成的,都能正常触发交互,不需要在每次生成DOM后重新绑定:

$(document).on('click', '.next', function() {
  // 沿DOM树向上找最近的章节容器,替代原来两层parent的定位方式,避免找错节点
  const $currentChapter = $(this).closest('.quiz-chapter');
  const userAnswers = collectChapterAnswers($currentChapter);
  const checkResult = validateCurrentChapter($currentChapter, userAnswers);
  if (!checkResult.passed) {
    alert(checkResult.tip);
    return;
  }
  // 校验通过才执行章节切换
  $currentChapter.hide();
  const $nextChapter = $currentChapter.next('.quiz-chapter');
  if ($nextChapter.length) {
    $nextChapter.show();
    // 切换后自动滚动到章节顶部,优化操作体验
    $('html, body').animate({scrollTop: $nextChapter.offset().top}, 300);
  } else {
    alert('已完成所有章节的评估测试');
  }
});
// 上一步跳转不需要做校验,直接切换即可
$(document).on('click', '.back', function() {
  const $currentChapter = $(this).closest('.quiz-chapter');
  $currentChapter.hide();
  const $prevChapter = $currentChapter.prev('.quiz-chapter');
  if ($prevChapter.length) {
    $prevChapter.show();
    $('html, body').animate({scrollTop: $prevChapter.offset().top}, 300);
  }
});

补充说明:前端校验仅用于优化交互体验,最终的作答对错判定必须在后端接口做兜底,避免用户通过修改前端DOM绕过校验直接跳转到后续章节。

内容的提问来源于stack exchange,提问作者DENNIS D'CRUZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 11:36:01