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
<script lang="ts" setup>
import type { QuestionFormModel, QuestionOption, QuestionType } from '../types';
 
import { computed } from 'vue';
 
import { OPTION_LABELS } from '../constants';
import { createDefaultOptions } from '../parseAnswer';
 
const model = defineModel<QuestionFormModel>({ required: true });
 
const type = computed(() => model.value.questionType);
 
function relabel(options: QuestionOption[], qType: QuestionType) {
  return options.map((opt, i) => ({
    ...opt,
    sortNo: i + 1,
    optionLabel: qType === 'blank' ? String(i + 1) : OPTION_LABELS[i] || String(i + 1),
  }));
}
 
function addOption() {
  const qType = type.value;
  const next = [...model.value.options];
  if (qType === 'blank') {
    next.push({ sortNo: next.length + 1, optionLabel: String(next.length + 1), optionContent: '', isCorrect: '1' });
  } else {
    if (next.length >= OPTION_LABELS.length) return;
    next.push({
      sortNo: next.length + 1,
      optionLabel: OPTION_LABELS[next.length],
      optionContent: '',
      isCorrect: '0',
    });
  }
  model.value.options = relabel(next, qType);
}
 
function removeOption(index: number) {
  const qType = type.value;
  const min = qType === 'blank' ? 1 : 2;
  if (model.value.options.length <= min) return;
  const next = model.value.options.filter((_, i) => i !== index);
  model.value.options = relabel(next, qType);
}
 
function onSingleCorrect(index: number) {
  model.value.options = model.value.options.map((opt, i) => ({
    ...opt,
    isCorrect: i === index ? '1' : '0',
  }));
}
 
function onMultiCorrect(index: number, checked: boolean) {
  model.value.options = model.value.options.map((opt, i) =>
    i === index ? { ...opt, isCorrect: checked ? '1' : '0' } : opt,
  );
}
 
function resetIfEmpty() {
  if (!model.value.options?.length) {
    model.value.options = createDefaultOptions(type.value);
  }
}
 
resetIfEmpty();
</script>
 
<template>
  <div class="answer-settings">
    <!-- 单选 -->
    <template v-if="type === 'single'">
      <a-button type="link" class="!px-0 mb-2" @click="addOption">增加选项</a-button>
      <div v-for="(opt, index) in model.options" :key="index" class="option-row">
        <a-radio :checked="opt.isCorrect === '1'" @change="onSingleCorrect(index)" />
        <span class="option-label">选项{{ opt.optionLabel }}</span>
        <a-input v-model:value="opt.optionContent" placeholder="请输入选项内容" class="flex-1" />
        <a class="text-primary" @click="removeOption(index)">移除</a>
      </div>
    </template>
 
    <!-- 多选 -->
    <template v-else-if="type === 'multi'">
      <a-button type="link" class="!px-0 mb-2" @click="addOption">增加选项</a-button>
      <div v-for="(opt, index) in model.options" :key="index" class="option-row option-row--multi">
        <a-checkbox :checked="opt.isCorrect === '1'" @change="(e: any) => onMultiCorrect(index, !!e?.target?.checked)" />
        <span class="option-label">选项{{ opt.optionLabel }}</span>
        <a-textarea v-model:value="opt.optionContent" :rows="2" placeholder="请输入选项内容" class="flex-1" />
        <a class="text-primary self-start mt-1" @click="removeOption(index)">移除</a>
      </div>
    </template>
 
    <!-- 判断 -->
    <template v-else-if="type === 'judge'">
      <a-radio-group v-model:value="model.judgeAnswer">
        <a-radio :value="true">正确</a-radio>
        <a-radio :value="false">错误</a-radio>
      </a-radio-group>
    </template>
 
    <!-- 填空 -->
    <template v-else-if="type === 'blank'">
      <div class="mb-2 flex items-center gap-4">
        <a-button type="link" class="!px-0" @click="addOption">增加填空</a-button>
        <a-checkbox v-model:checked="model.blankMixMode">混杂模式批改</a-checkbox>
      </div>
      <div v-for="(opt, index) in model.options" :key="index" class="option-row">
        <span class="option-label">填空{{ opt.optionLabel }}</span>
        <a-input v-model:value="opt.optionContent" placeholder="请输入标准答案" class="flex-1" />
        <a class="text-primary" @click="removeOption(index)">移除</a>
      </div>
    </template>
 
    <!-- 问答 -->
    <template v-else-if="type === 'essay'">
      <a-textarea v-model:value="model.essayAnswer" :rows="5" placeholder="请输入参考答案 / 评分要点" />
    </template>
  </div>
</template>
 
<style scoped>
.option-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.option-row--multi {
  align-items: flex-start;
}
.option-label {
  width: 56px;
  flex-shrink: 0;
  color: rgba(0, 0, 0, 0.65);
}
</style>