{"version":3,"file":"single-model.cjs","sources":["../../../../packages/components/src/subject/single-model.ts"],"sourcesContent":["import type { AnswerType } from './types'\nimport { SubjectError, type TagItem, trimText } from './subject-shared'\n\nexport interface SingleAnswer {\n  title: string\n  isCorrect: boolean\n  customAnswerId?: string | number\n  answerId?: string | number\n  resultItem?: string\n  orderIndex?: number\n  answerRelations?: any[]\n  relationType?: number | null\n  [key: string]: any\n}\n\nexport interface SingleSnapshot {\n  title: string\n  answers: SingleAnswer[]\n  analysis: string\n  leastAnswerCount: number | null\n  selectedTagList: TagItem[]\n  examExpand: string\n  showRichText: boolean\n  richText: string\n  orderList: string[]\n}\n\nexport interface SingleEditorState {\n  title: string\n  analysis: string\n  leastAnswerCount: number | null\n  answerCheckType: number\n  isKey: boolean\n  selectedTagList: TagItem[]\n  categoryId: string\n  richText: string\n  showRichText: boolean\n  answers?: SingleAnswer[]\n  orderList?: string[]\n}\n\nexport interface SingleValidationResult {\n  errors: SubjectError[]\n  isSetCorrectAnswer: boolean\n  correctAnswerCount: number\n}\n\nfunction createEmptySingleAnswer(): SingleAnswer {\n  return { title: '', isCorrect: false }\n}\n\nexport function createDefaultSingleAnswers(): SingleAnswer[] {\n  return [\n    createEmptySingleAnswer(),\n    createEmptySingleAnswer(),\n    createEmptySingleAnswer(),\n    createEmptySingleAnswer(),\n  ]\n}\n\nexport function supportsLeastAnswerCount(answerType: AnswerType) {\n  return answerType === 'multiple' || answerType === 'sort'\n}\n\nexport function normalizeLeastAnswerCount(value: unknown, answerType: AnswerType): number | null {\n  if (!supportsLeastAnswerCount(answerType) || value === '' || value === null || value === undefined) {\n    return null\n  }\n  const count = Number(value)\n  return Number.isFinite(count) && count > 0 ? count : null\n}\n\nexport function leastAnswerCountSuffix(value: number | null, answerType: AnswerType) {\n  if (!supportsLeastAnswerCount(answerType) || value === null) {\n    return ''\n  }\n  return `，至少选${value}项${answerType === 'sort' ? '并排序' : ''}`\n}\n\nexport function normalizeSingleAnswerItem(answer: any): SingleAnswer {\n  const next: SingleAnswer = {\n    ...answer,\n    title: trimText(answer?.title ?? answer?.answer ?? ''),\n    isCorrect: !!answer?.isCorrect,\n  }\n  const answerId = answer?.answerId ?? answer?.examAnswerId\n  if (answerId !== undefined) {\n    next.answerId = answerId\n  }\n  return next\n}\n\nexport function normalizeSingleAnswerList(value: unknown): SingleAnswer[] {\n  const answers = Array.isArray(value) ? value : []\n  return answers.length\n    ? answers.map(answer => normalizeSingleAnswerItem(answer))\n    : createDefaultSingleAnswers()\n}\n\nexport function resolveSingleOrderList({\n  examExpand,\n  answers,\n  labelForIndex,\n}: {\n  examExpand?: string\n  answers?: any[]\n  labelForIndex: (index: number) => string\n}): string[] {\n  if (!examExpand || !answers?.length) {\n    return []\n  }\n\n  return examExpand\n    .split(',')\n    .map((id) => {\n      const index = answers.findIndex((answer, answerIndex) =>\n        String(answer.answerId ?? answer.orderIndex ?? (answerIndex + 1)) === String(id),\n      )\n      return index >= 0 ? labelForIndex(index) : ''\n    })\n    .filter(Boolean)\n}\n\nexport function buildSingleEditorState({\n  answerType,\n  title,\n  analysis,\n  leastAnswerCount,\n  answerCheckType,\n  isKey,\n  tagList,\n  categoryId,\n  richTextContent,\n  answerList,\n  examExpand,\n  labelForIndex,\n  includeOrderList = false,\n}: {\n  answerType: AnswerType\n  title?: string\n  analysis?: string\n  leastAnswerCount?: unknown\n  answerCheckType?: number\n  isKey?: boolean\n  tagList?: unknown\n  categoryId?: unknown\n  richTextContent?: string\n  answerList?: unknown\n  examExpand?: string\n  labelForIndex: (index: number) => string\n  includeOrderList?: boolean\n}): SingleEditorState {\n  const answers = Array.isArray(answerList) && answerList.length\n    ? answerList.map(answer => normalizeSingleAnswerItem(answer))\n    : undefined\n\n  const orderList = includeOrderList && Array.isArray(answerList) && answerList.length && examExpand\n    ? resolveSingleOrderList({ examExpand, answers: answerList, labelForIndex })\n    : undefined\n\n  return {\n    title: title || '',\n    analysis: analysis || '',\n    leastAnswerCount: normalizeLeastAnswerCount(leastAnswerCount, answerType),\n    answerCheckType: answerCheckType || 1,\n    isKey: !!isKey,\n    selectedTagList: Array.isArray(tagList) ? tagList.map(item => ({ ...item })) : [],\n    categoryId: categoryId ? String(categoryId) : '',\n    richText: richTextContent || '',\n    showRichText: !!richTextContent,\n    answers,\n    orderList,\n  }\n}\n\nexport function buildSingleSnapshot({\n  answerType,\n  title,\n  answers,\n  analysis,\n  leastAnswerCount,\n  selectedTagList,\n  examExpand,\n  showRichText,\n  richText,\n  orderList,\n  sortAnswerValue,\n}: {\n  answerType: AnswerType\n  title?: string\n  answers?: any[]\n  analysis?: string\n  leastAnswerCount?: unknown\n  selectedTagList?: TagItem[]\n  examExpand?: string\n  showRichText?: boolean\n  richText?: string\n  orderList?: string[]\n  sortAnswerValue?: (letter: string) => string | number\n}): SingleSnapshot {\n  const normalizedAnswers = (Array.isArray(answers) ? answers : []).map(answer => ({\n    ...normalizeSingleAnswerItem(answer),\n    resultItem: trimText(answer?.resultItem ?? ''),\n  }))\n  const normalizedOrderList = Array.isArray(orderList) ? orderList.filter(Boolean) : []\n\n  return {\n    title: trimText(title ?? ''),\n    answers: normalizedAnswers,\n    analysis: trimText(analysis ?? ''),\n    leastAnswerCount: normalizeLeastAnswerCount(leastAnswerCount, answerType),\n    selectedTagList: Array.isArray(selectedTagList) ? [...selectedTagList] : [],\n    examExpand: typeof sortAnswerValue === 'function'\n      ? normalizedOrderList.map(letter => sortAnswerValue(letter)).join(',')\n      : (examExpand || ''),\n    showRichText: !!showRichText,\n    richText: richText || '',\n    orderList: normalizedOrderList,\n  }\n}\n\nexport function validateSingleSnapshot(\n  snapshot: SingleSnapshot,\n  answerType: AnswerType,\n  row?: any,\n): SingleValidationResult {\n  const errors: SubjectError[] = []\n\n  if (!snapshot.title) {\n    errors.push(new SubjectError('题目标题不能为空!', 'EMPTY_TITLE', 'title', row))\n  }\n\n  let isSetCorrectAnswer = false\n  let correctAnswerCount = 0\n\n  snapshot.answers.forEach((answer, index) => {\n    if (!answer.title?.trim()) {\n      errors.push(new SubjectError(`选项${String.fromCharCode(65 + index)}未填写`, 'ANSWER_EMPTY', 'answers', row))\n    }\n    if (answerType !== 'sort' && answer.isCorrect) {\n      isSetCorrectAnswer = true\n      correctAnswerCount++\n    }\n  })\n\n  const titleSet = new Set(snapshot.answers.map(answer => answer.title))\n  if (titleSet.size !== snapshot.answers.length && snapshot.answers.length > 0) {\n    errors.push(new SubjectError('选项不能重复', 'DUPLICATE_ANSWERS', 'answers', row))\n  }\n\n  if (answerType === 'single' && correctAnswerCount > 1) {\n    errors.push(new SubjectError(\n      '此题为单选题，设置了多个推荐/正确选项，请保存时确认是否切换为多选题',\n      'SINGLE_MULTI_CORRECT',\n      'answers',\n      row,\n    ))\n  }\n\n  if (answerType === 'multiple') {\n    if (correctAnswerCount === 1) {\n      errors.push(new SubjectError('请设置至少两个推荐/正确选项', 'CORRECT_COUNT_INVALID', 'answers', row))\n    }\n    if (correctAnswerCount > 0) {\n      isSetCorrectAnswer = true\n    }\n    if (isSetCorrectAnswer && snapshot.leastAnswerCount !== null && correctAnswerCount < snapshot.leastAnswerCount) {\n      errors.push(new SubjectError('至少选几项与推荐/正确选项数不符', 'LEAST_ANSWER_COUNT_INVALID', 'answers', row))\n    }\n  }\n\n  if (answerType === 'sort') {\n    isSetCorrectAnswer = snapshot.orderList.length > 0\n    if (snapshot.leastAnswerCount !== null && snapshot.orderList.length < snapshot.leastAnswerCount) {\n      errors.push(new SubjectError('至少选几项与推荐/正确选项数不符', 'LEAST_ANSWER_COUNT_INVALID', 'orderList', row))\n    }\n  }\n\n  return {\n    errors,\n    isSetCorrectAnswer,\n    correctAnswerCount,\n  }\n}\n\nexport function serializeSingleSnapshot(\n  snapshot: SingleSnapshot,\n  {\n    answerType,\n    isSetCorrectAnswer,\n    examAnswerRelationType = 0,\n    customId = '',\n  }: {\n    answerType: AnswerType\n    isSetCorrectAnswer: boolean\n    examAnswerRelationType?: number\n    customId?: string\n  },\n) {\n  const result: any = {\n    answerType: String(answerType),\n    examTypeEnum: String(answerType),\n    title: snapshot.title,\n    answers: snapshot.answers.map((answer, index) => {\n      const relationType = answer.resultItem\n        ? 1\n        : (Array.isArray(answer.answerRelations) && answer.answerRelations.length ? 2 : null)\n      const next: any = { ...answer, orderIndex: index + 1, answer: answer.title, relationType }\n      if (answer.answerId !== undefined) {\n        next.examAnswerId = answer.answerId\n      }\n      if (relationType === null) {\n        delete next.relationType\n      }\n      return next\n    }),\n    examExpand: snapshot.examExpand,\n    analysis: snapshot.analysis,\n    isSetCorrectAnswer,\n    examRichTextContent: snapshot.showRichText ? snapshot.richText : '',\n  }\n\n  if (examAnswerRelationType) {\n    result.examAnswerRelationType = examAnswerRelationType\n  }\n  if (supportsLeastAnswerCount(answerType)) {\n    result.leastAnswerCount = snapshot.leastAnswerCount\n  }\n  if (customId) {\n    result.customId = customId\n  }\n\n  return result\n}\n"],"names":["createEmptySingleAnswer","createDefaultSingleAnswers","supportsLeastAnswerCount","answerType","normalizeLeastAnswerCount","value","count","leastAnswerCountSuffix","normalizeSingleAnswerItem","answer","next","trimText","answerId","normalizeSingleAnswerList","answers","resolveSingleOrderList","examExpand","labelForIndex","id","index","answerIndex","buildSingleEditorState","title","analysis","leastAnswerCount","answerCheckType","isKey","tagList","categoryId","richTextContent","answerList","includeOrderList","orderList","item","buildSingleSnapshot","selectedTagList","showRichText","richText","sortAnswerValue","normalizedAnswers","normalizedOrderList","letter","validateSingleSnapshot","snapshot","row","errors","SubjectError","isSetCorrectAnswer","correctAnswerCount","serializeSingleSnapshot","examAnswerRelationType","customId","result","relationType"],"mappings":"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"}