Files
shanghai-residences/src/components/layout/quiz
zhongyidian f5f36f75b5 feat: add puzzle residence configuration and reflection progress logic
- Introduced `puzzleResidences.ts` to define puzzle residence configurations including properties like display name, position, and puzzle availability.
- Added `reflectionProgress.ts` to manage badge unlocking logic based on place completion, including functions to determine unlocked badges and video sources for scenes.
2026-04-27 11:49:30 +08:00
..

Quiz Panel 组件

用于展示单选题和多选题的面板组件,内部管理选择状态,通过 onSubmit 回调通知外部。

组件列表

  • SingleChoiceQuizPanel - 单选题面板
  • MultipleChoiceQuizPanel - 多选题面板
  • SelectFillQuizPanel - 选择填空题面板
  • QuizPanel - 旧版组件(已废弃,保留以保持向后兼容)

SelectFillQuizPanel - 选择填空题面板

功能特性

  • ✅ 支持多个空依次填写
  • ✅ 下方提供一组可点击选项(如数字 0-9)
  • ✅ 内部管理答题状态与当前激活空
  • ✅ 支持正确答案校验与错误提示
  • ✅ 关闭面板时自动重置内部状态

使用示例

import { SelectFillQuizPanel } from "@/components";

function MyComponent() {
  const [showQuiz, setShowQuiz] = useState(false);

  return (
    <SelectFillQuizPanel
      visible={showQuiz}
      titlePrefix="【填空】毛泽东主席认为,到了"
      titleSuffix="年夏天,在理论上,而且在某种程度的行动上,他已成为一个马克思主义者。"
      blanks={[
        { id: "year", prefix: "____" },
      ]}
      options={[
        { value: "1919", label: "1919" },
        { value: "1920", label: "1920" },
        { value: "1921", label: "1921" },
      ]}
      correctAnswers={{ year: "1920" }}
      errorMessage="回想一下 1920 年 5 月到 7 月在上海居住的这段经历~"
      onSubmit={(results, isCorrect) => {
        console.log("选择结果:", results, "是否正确:", isCorrect);
        if (isCorrect) {
          setShowQuiz(false);
        }
      }}
      onError={(error) => {
        console.log("错误信息:", error);
      }}
      submitText="确定"
    />
  );
}

API

属性 类型 默认值 说明
visible boolean - 是否可见(必填)
zIndex number 10000 z-index 层级
titlePrefix string - 整体题干前缀文本(可选)
titleSuffix string - 整体题干后缀文本(可选)
blanks SelectFillBlank[] - 每个填空位的配置(必填,包含 id / prefix / suffix)
options { value: string; label: string }[] - 候选项列表(必填)
correctAnswers Record<string, string> - 正确答案映射(可选,不传则不做校验,直接判定为正确)
errorMessage string "还不太对,再仔细对照题干和提示想一想吧~" 自定义错误提示信息(答案错误时显示)
onSubmit (results: SelectFillResult[], isCorrect: boolean) => void - 提交回调
onError (error: string) => void - 错误回调
disabled boolean false 是否禁用
submitText string "提交" 提交按钮文本

行为说明

  1. 点击空格:切换当前激活的填空位。
  2. 点击下方选项:将选项填入当前激活的空中,并自动跳转到下一个未填写的空。
  3. 点击空中的 ×:清除该空的内容,并把当前激活位置移动到该空。
  4. 点击提交:如果有空未填,给出“请先把所有空都填完再提交哦~”提示;如果提供了 correctAnswers,会逐空校验是否全部正确。
  5. 答案正确:调用 onSubmit(results, true),同时清除错误提示。
  6. 答案错误:显示错误提示,仅调用 onError(error),不调用 onSubmit(false)。
  7. 未提供正确答案:直接调用 onSubmit(results, true),不进行校验。
  8. 关闭面板(visible 从 true 变为 false):内部会自动重置所有填空和错误提示。

SingleChoiceQuizPanel - 单选题面板

功能特性

  • ✅ 内部管理选择状态
  • ✅ 点击选项后自动提交
  • ✅ 支持答案验证(可选)
  • ✅ 自动显示错误提示
  • ✅ 关闭面板时自动重置内部状态

使用方法

import { SingleChoiceQuizPanel } from "@/components";

function MyComponent() {
  const [showQuiz, setShowQuiz] = useState(false);

  return (
    <SingleChoiceQuizPanel
      visible={showQuiz}
      title="这是一道单选题:以下哪个选项是正确的?"
      options={[
        { value: "A", label: "选项A" },
        { value: "B", label: "选项B" },
        { value: "C", label: "选项C" },
      ]}
      correctAnswer="B"
      errorMessage="再想一想,注意题干中的时间和提示信息哦~"
      onSubmit={(value, isCorrect) => {
        console.log("用户选择:", value);
        console.log("是否正确:", isCorrect);
        if (isCorrect) {
          // 选择正确,可以关闭面板或进入下一步
          setShowQuiz(false);
        }
      }}
      onError={(error) => {
        console.log("错误信息:", error);
      }}
    />
  );
}

API

属性 类型 默认值 说明
属性 类型 默认值 说明
------ ------ -------- ------
visible boolean - 是否可见(必填)
zIndex number 10000 z-index 层级
title string - 题目(必填)
options SingleChoiceOption[] - 选项列表(必填)
correctAnswer string - 正确答案(可选,用于验证)
errorMessage string "很抱歉,你选错了!请你再思考一下吧!" 自定义错误提示信息(答案错误时显示)
onSubmit (value: string, isCorrect: boolean) => void - 提交回调
onError (error: string) => void - 错误回调
disabled boolean false 是否禁用

行为说明

  1. 点击选项:立即触发提交,如果提供了 correctAnswer,会自动验证
  2. 答案正确:调用 onSubmit(value, true),并清空内部选择与错误状态
  3. 答案错误:显示错误提示,仅调用 onError(error),并清空内部选择状态
  4. 未提供正确答案:直接调用 onSubmit(value, true),不进行验证
  5. 关闭面板(visible 从 true 变为 false):内部会自动重置已选择的值和错误提示

MultipleChoiceQuizPanel - 多选题面板

功能特性

  • ✅ 内部管理多选状态
  • ✅ 支持最小/最大选择数量限制
  • ✅ 通过提交按钮提交
  • ✅ 支持答案验证(可选)
  • ✅ 自动显示错误提示
  • ✅ 提交后禁用交互

使用方法

import { MultipleChoiceQuizPanel } from "@/components";

function MyComponent() {
  const [showQuiz, setShowQuiz] = useState(false);

  return (
    <MultipleChoiceQuizPanel
      visible={showQuiz}
      title="这是一道多选题:以下哪些选项是正确的?(可多选)"
      options={[
        { value: "A", label: "选项A" },
        { value: "B", label: "选项B" },
        { value: "C", label: "选项C" },
        { value: "D", label: "选项D" },
      ]}
      correctAnswer={["A", "B"]}
      errorMessage="很抱歉,你选错了!请你再思考一下吧!"
      minSelections={1}
      maxSelections={3}
      minSelectionsErrorMessage="请至少选择 1 项才能提交"
      submitText="确认提交"
      onSubmit={(values, isCorrect) => {
        console.log("用户选择:", values);
        console.log("是否正确:", isCorrect);
        if (isCorrect) {
          setShowQuiz(false);
        }
      }}
      onError={(error) => {
        console.log("错误信息:", error);
      }}
    />
  );
}

API

属性 类型 默认值 说明
属性 类型 默认值 说明
------ ------ -------- ------
visible boolean - 是否可见(必填)
zIndex number 10000 z-index 层级
title string - 题目(必填)
options MultipleChoiceOption[] - 选项列表(必填)
correctAnswer string[] - 正确答案数组(可选,用于验证)
errorMessage string "很抱歉,你选错了!请你再思考一下吧!" 自定义错误提示信息(答案错误时显示)
minSelectionsErrorMessage string 请至少选择 ${minSelections} 项 自定义最小选择数量不足时的提示信息
onSubmit (values: string[], isCorrect: boolean) => void - 提交回调
onError (error: string) => void - 错误回调
disabled boolean false 是否禁用
minSelections number - 最小选择数量
maxSelections number - 最大选择数量
submitText string "提交" 提交按钮文本

行为说明

  1. 选择选项:点击选项进行多选,受 minSelections 和 maxSelections 限制
  2. 点击提交:验证最小选择数量,如果提供了 correctAnswer,会验证答案
  3. 答案正确:调用 onSubmit(values, true),面板进入已提交状态
  4. 答案错误:显示错误提示,调用 onError(error) 和 onSubmit(values, false)
  5. 未提供正确答案:直接调用 onSubmit(values, true),不进行验证

迁移指南

从旧版 QuizPanel 迁移

旧版用法:

<QuizPanel
  visible={showQuiz}
  title="题目"
  options={options}
  value={quizAnswer}
  error={quizError}
  onChange={(val) => {
    setQuizAnswer(val);
    if (val === "B") {
      setQuizError("");
    } else {
      setQuizError("很抱歉,你选错了!");
    }
  }}
/>

新版用法:

<SingleChoiceQuizPanel
  visible={showQuiz}
  title="题目"
  options={options}
  correctAnswer="B"
  onSubmit={(value, isCorrect) => {
    if (isCorrect) {
      // 选择正确
    } else {
      // 选择错误,错误信息已由组件内部显示
    }
  }}
/>

主要变化

  1. 不再需要 onChange:组件内部管理选择状态
  2. 不再需要 value 和 error:组件内部管理
  3. 使用 onSubmit:替代 onChange,返回用户选择和是否正确
  4. 使用 correctAnswer:让组件自动验证答案
  5. 使用 onError:可选,用于处理错误信息

注意事项

  1. 两个组件都使用内部状态管理,不需要外部传入 value
  2. 如果提供了 correctAnswer,组件会自动验证并显示错误信息
  3. 当 visible 从 true 变为 false 时,单选题和多选题面板都会自动重置内部选择与错误状态,便于下次重新答题
  4. 多选题的答案比较不考虑顺序,只要选择的选项和正确答案一致即可
  5. 旧版 QuizPanel 仍然可用,但建议迁移到新组件