liuyu
4 小时以前 82a74ba0402ab546ba524d23ce62198c4d00d2f7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import type { QuestionEntity, QuestionFormModel, QuestionOption, QuestionType } from './types';
 
import { OPTION_LABELS } from './constants';
 
/** 按题型生成默认答案区 */
export function createDefaultOptions(type: QuestionType): QuestionOption[] {
  if (type === 'single' || type === 'multi') {
    return OPTION_LABELS.slice(0, 4).map((label, i) => ({
      sortNo: i + 1,
      optionLabel: label,
      optionContent: '',
      isCorrect: '0',
    }));
  }
  if (type === 'judge') {
    return [
      { sortNo: 1, optionLabel: 'T', optionContent: '正确', isCorrect: '1' },
      { sortNo: 2, optionLabel: 'F', optionContent: '错误', isCorrect: '0' },
    ];
  }
  if (type === 'blank') {
    return [{ sortNo: 1, optionLabel: '1', optionContent: '', isCorrect: '1' }];
  }
  // essay:参考答案存在 option[0]
  return [{ sortNo: 1, optionLabel: 'A', optionContent: '', isCorrect: '1' }];
}
 
/** 表单 → 落库实体(各题型解析) */
export function parseFormToEntity(form: QuestionFormModel): Omit<QuestionEntity, 'bankName' | 'adminUserName' | 'creatorTime'> {
  const options = parseOptionsByType(form);
  return {
    id: form.id,
    bankId: form.bankId || '',
    questionType: form.questionType,
    difficulty: form.difficulty,
    sourceType: form.sourceType,
    stem: form.stem,
    analysis: form.analysis,
    bizStatus: form.bizStatus,
    blankMixMode: form.questionType === 'blank' ? form.blankMixMode : undefined,
    options,
  };
}
 
export function parseOptionsByType(form: QuestionFormModel): QuestionOption[] {
  const { questionType } = form;
  if (questionType === 'judge') {
    const correct = form.judgeAnswer !== false;
    return [
      { sortNo: 1, optionLabel: 'T', optionContent: '正确', isCorrect: correct ? '1' : '0' },
      { sortNo: 2, optionLabel: 'F', optionContent: '错误', isCorrect: correct ? '0' : '1' },
    ];
  }
  if (questionType === 'essay') {
    return [
      {
        sortNo: 1,
        optionLabel: 'A',
        optionContent: form.essayAnswer ?? '',
        isCorrect: '1',
      },
    ];
  }
  // single / multi / blank:直接用 options,并重排 label
  return (form.options || []).map((opt, i) => ({
    ...opt,
    sortNo: i + 1,
    optionLabel: questionType === 'blank' ? String(i + 1) : OPTION_LABELS[i] || String(i + 1),
  }));
}
 
/** 实体 → 表单回填(各题型解析) */
export function hydrateFormFromEntity(entity: QuestionEntity): QuestionFormModel {
  const type = entity.questionType;
  const options = entity.options?.length ? [...entity.options] : createDefaultOptions(type);
  const form: QuestionFormModel = {
    id: entity.id,
    questionType: type,
    bankId: entity.bankId,
    difficulty: entity.difficulty || 'normal',
    sourceType: entity.sourceType || 'self',
    bizStatus: entity.bizStatus || 'closed',
    stem: entity.stem || '',
    analysis: entity.analysis || '',
    options,
    blankMixMode: !!entity.blankMixMode,
    judgeAnswer: true,
    essayAnswer: '',
  };
 
  if (type === 'judge') {
    const correct = options.find((o) => o.isCorrect === '1');
    form.judgeAnswer = !correct || correct.optionLabel === 'T' || correct.optionContent === '正确';
  } else if (type === 'essay') {
    form.essayAnswer = options[0]?.optionContent || '';
  }
  return form;
}
 
/** 提交前校验(按题型) */
export function validateAnswerByType(form: QuestionFormModel): string | null {
  if (!form.bankId) return '请选择所属题库';
  if (!form.stem?.trim()) return '请填写题干内容';
 
  switch (form.questionType) {
    case 'single': {
      const filled = form.options.filter((o) => o.optionContent?.trim());
      if (filled.length < 2) return '单选题至少填写 2 个选项';
      if (form.options.filter((o) => o.isCorrect === '1').length !== 1) return '单选题必须且只能选择 1 个正确答案';
      break;
    }
    case 'multi': {
      const filled = form.options.filter((o) => o.optionContent?.trim());
      if (filled.length < 2) return '多选题至少填写 2 个选项';
      if (form.options.filter((o) => o.isCorrect === '1').length < 2) return '多选题至少选择 2 个正确答案';
      break;
    }
    case 'judge':
      if (form.judgeAnswer === undefined) return '请选择判断题答案';
      break;
    case 'blank': {
      if (!form.options.length) return '请至少增加一个填空';
      if (form.options.some((o) => !o.optionContent?.trim())) return '请填写每个填空的答案';
      break;
    }
    case 'essay':
      if (!form.essayAnswer?.trim()) return '请填写问答题参考答案';
      break;
  }
  return null;
}
 
/** 切换题型时重置答案区 */
export function resetAnswerForType(type: QuestionType): Pick<QuestionFormModel, 'options' | 'judgeAnswer' | 'essayAnswer' | 'blankMixMode'> {
  return {
    options: createDefaultOptions(type),
    judgeAnswer: true,
    essayAnswer: '',
    blankMixMode: false,
  };
}