|
|
@@ -5,47 +5,66 @@
|
|
|
{{ questionTypeDesc[question.typeId as EnumQuestionType] }}
|
|
|
</view>
|
|
|
<view class="question-content" :class="{ 'mt-30': isSubQuestion }">
|
|
|
- <uv-parse :content="getQuestionTitle()"></uv-parse>
|
|
|
+ <text class="text-nowrap text-30">{{ getQuestionTitle() }} </text>
|
|
|
+ <uv-parse :content="question.title" containerStyle="display:inline"
|
|
|
+ contentStyle="word-break:break-word;"></uv-parse>
|
|
|
</view>
|
|
|
<view class="question-options">
|
|
|
<view class="question-option" v-for="option in question.options" :class="getStyleClass(option)" :key="option.id"
|
|
|
@click="handleSelect(option)">
|
|
|
- <view v-if="!readonly" class="question-option-index">{{ option.no }}</view>
|
|
|
+ <template v-if="!readonly">
|
|
|
+ <view v-if="!isOnlySubjective" class="question-option-index">{{ option.no }}</view>
|
|
|
+ <view v-else>
|
|
|
+ <uv-icon name="info-circle" :color="question.isNotKnow ? '#31A0FC' : '#999'" size="18" />
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
<view v-else>
|
|
|
<uv-icon v-if="isOptionCorrect(option)" name="checkmark-circle-fill" color="#2CC6A0" size="22" />
|
|
|
<uv-icon v-else-if="isOptionIncorrect(option)" name="close-circle-fill" color="#FF5B5C" size="22" />
|
|
|
<view v-else class="question-option-index">{{ option.no }}</view>
|
|
|
</view>
|
|
|
<view class="question-option-content">
|
|
|
- <uv-parse :content="option.name"></uv-parse>
|
|
|
+ <uv-parse :content="getOptionContent(option)" containerStyle="display:inline"
|
|
|
+ contentStyle="word-break:break-word;"></uv-parse>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view v-if="question.options.length && !readonly" class="question-option"
|
|
|
+ <view v-if="question.options.length && !readonly && !isOnlySubjective" class="question-option"
|
|
|
:class="{ 'question-option-not-know': question.isNotKnow }" @click="handleNotKnow">
|
|
|
<view class="question-option-index">
|
|
|
<uv-icon name="info-circle" :color="question.isNotKnow ? '#31A0FC' : '#999'" size="18" />
|
|
|
</view>
|
|
|
<view class="question-option-content text-fore-light">不会</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
- <view v-if="readonly" class="answer-wrap mt-40 rounded-8 pt-60 pb-40 flex items-center text-center relative">
|
|
|
- <ie-image v-if="question.isCorrect" src="/pagesStudy/static/image/icon-answer-correct.png"
|
|
|
- class="absolute top-0 left-1/2 -translate-x-1/2 w-222 h-64" />
|
|
|
- <ie-image v-else src="/pagesStudy/static/image/icon-answer-incorrect.png"
|
|
|
- class="absolute top-0 left-1/2 -translate-x-1/2 w-240 h-64" />
|
|
|
- <view class="flex-1">
|
|
|
- <view class="text-34 text-[#2CC6A0] font-bold">{{ question.answer1 }}</view>
|
|
|
- <view class="mt-4 text-26">正确答案</view>
|
|
|
- </view>
|
|
|
- <view class="h-40 w-1 bg-back"></view>
|
|
|
- <view class="flex-1">
|
|
|
- <view class="text-34 font-bold" :class="[question.isCorrect ? 'text-[#2CC6A0]' : 'text-[#FF5B5C]']">
|
|
|
- {{ question.answers.join('') || (question.isNotKnow ? '不会' : '未答') }}
|
|
|
+ <view v-if="!readonly && isOnlySubjective" class="mt-40 bg-[#EBF9FF] p-12 rounded-8">
|
|
|
+ <view class="rounded-8 bg-white px-10 py-20 text-primary text-24 flex gap-x-6 items-center">
|
|
|
+ <uv-icon name="info-circle" color="#31A0FC" size="16" />
|
|
|
+ <text>主观题请线下答题,查看解析对比后,选“会”或“不会”</text>
|
|
|
</view>
|
|
|
- <view class="mt-4 text-26">我的答案</view>
|
|
|
+ <view class="mt-30 mb-20 text-24 text-white bg-primary w-fit mx-auto px-20 py-12 rounded-full text-center" @click="handleShowParse">
|
|
|
+ 查看解析</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view v-if="question.parse" class="mt-40">
|
|
|
+ <!-- 阅卷模式下显示答案 -->
|
|
|
+ <template v-if="readonly">
|
|
|
+ <view class="answer-wrap mt-40 rounded-8 pt-60 pb-40 flex items-center text-center relative">
|
|
|
+ <ie-image v-if="question.isCorrect" src="/pagesStudy/static/image/icon-answer-correct.png"
|
|
|
+ class="absolute top-0 left-1/2 -translate-x-1/2 w-222 h-64" />
|
|
|
+ <ie-image v-else src="/pagesStudy/static/image/icon-answer-incorrect.png"
|
|
|
+ class="absolute top-0 left-1/2 -translate-x-1/2 w-240 h-64" />
|
|
|
+ <view class="flex-1">
|
|
|
+ <view class="text-34 text-[#2CC6A0] font-bold">{{ question.answer1 }}</view>
|
|
|
+ <view class="mt-4 text-26">正确答案</view>
|
|
|
+ </view>
|
|
|
+ <view class="h-40 w-1 bg-back"></view>
|
|
|
+ <view class="flex-1">
|
|
|
+ <view class="text-34 font-bold" :class="[question.isCorrect ? 'text-[#2CC6A0]' : 'text-[#FF5B5C]']">
|
|
|
+ {{ question.answers.join('') || (question.isNotKnow ? '不会' : '未答') }}
|
|
|
+ </view>
|
|
|
+ <view class="mt-4 text-26">我的答案</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ <view v-if="(readonly && question.parse) || (!readonly && question.showParse)" class="mt-40">
|
|
|
<view class="text-30 text-fore-title font-bold">解析</view>
|
|
|
<view class="mt-10 text-26 text-fore-light">
|
|
|
<uv-parse :content="question.parse || '暂无解析'"></uv-parse>
|
|
|
@@ -53,9 +72,20 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
<view v-if="question.subQuestions.length" class="is-sub-question">
|
|
|
- <question-item :question="subQuestion" :readonly="readonly" v-for="(subQuestion, index) in question.subQuestions"
|
|
|
- :key="subQuestion.id" :is-sub-question="true" :index="index" :total="question.subQuestions.length"
|
|
|
- @update:question="handleSubQuestionUpdate" @select="handleSelectOption" @notKnow="handleSelectNotKnow" />
|
|
|
+ <scroll-view class="w-full h-fit sticky top-0 bg-white py-10 z-1" scroll-x>
|
|
|
+ <view class="flex items-center px-20 gap-x-20">
|
|
|
+ <view class="px-40 py-8 rounded-full"
|
|
|
+ :class="[subIndex === subQuestionIndex ? 'bg-[#EBF9FF] text-primary font-bold' : 'bg-back']"
|
|
|
+ v-for="(subQuestion, subIndex) in question.subQuestions" @click="handleSubQuestionClick(subIndex)">
|
|
|
+ {{ index + subIndex + 1 }}
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ <view v-if="subQuestion">
|
|
|
+ <question-item :question="subQuestion" :readonly="readonly" :is-sub-question="true" :index="index"
|
|
|
+ :total="question.subQuestions.length" @update:question="handleSubQuestionUpdate" @select="handleSelectOption"
|
|
|
+ @notKnow="handleSelectNotKnow" />
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
@@ -70,19 +100,28 @@ const props = defineProps<{
|
|
|
question: Study.Question;
|
|
|
readonly?: boolean;
|
|
|
isSubQuestion?: boolean;
|
|
|
- index?: number;
|
|
|
+ index: number;
|
|
|
total?: number;
|
|
|
+ subQuestionIndex?: number;
|
|
|
}>();
|
|
|
const nextQuestion = inject(NEXT_QUESTION);
|
|
|
const prevQuestion = inject(PREV_QUESTION);
|
|
|
const nextQuestionQuickly = inject(NEXT_QUESTION_QUICKLY);
|
|
|
const prevQuestionQuickly = inject(PREV_QUESTION_QUICKLY);
|
|
|
+const subQuestion = computed(() => {
|
|
|
+ return props.question.subQuestions[props.subQuestionIndex ?? 0];
|
|
|
+});
|
|
|
const emit = defineEmits<{
|
|
|
(e: 'update:question', question: Study.Question): void;
|
|
|
(e: 'select', question: Study.Question): void;
|
|
|
(e: 'notKnow', question: Study.Question): void;
|
|
|
(e: 'scrollTo', selector: string): void;
|
|
|
+ (e: 'changeSubQuestion', index: number): void;
|
|
|
+ (e: 'selectSubQuestion', index: number): void;
|
|
|
}>();
|
|
|
+const isOnlySubjective = computed(() => {
|
|
|
+ return props.question.typeId === EnumQuestionType.SUBJECTIVE;
|
|
|
+});
|
|
|
const getStyleClass = (option: Study.QuestionOption) => {
|
|
|
if (!props.readonly) {
|
|
|
return isSelected(option) ? 'question-option-selected' : '';
|
|
|
@@ -129,12 +168,18 @@ const isOptionIncorrect = (option: Study.QuestionOption) => {
|
|
|
const getQuestionTitle = () => {
|
|
|
if (props.isSubQuestion) {
|
|
|
const prefix = questionTypeDesc[props.question.typeId as EnumQuestionType].slice(0, 2);
|
|
|
- const qsOrder = props.total && props.total > 1 ? `${props.index! + 1}.` : '';
|
|
|
- return `[${prefix}] ${qsOrder} ${props.question.title}`;
|
|
|
+ return `[${prefix}]`;
|
|
|
}
|
|
|
- return props.question.title;
|
|
|
+ return '';
|
|
|
};
|
|
|
-
|
|
|
+const getOptionContent = (option: Study.QuestionOption) => {
|
|
|
+ // sb 问题,浪费几个小时
|
|
|
+ return option.name.replace(/\s/g, ' ');
|
|
|
+}
|
|
|
+const handleShowParse = () => {
|
|
|
+ props.question.showParse = !props.question.showParse;
|
|
|
+ emit('update:question', props.question);
|
|
|
+}
|
|
|
const handleNotKnow = () => {
|
|
|
props.question.answers = [];
|
|
|
props.question.isNotKnow = !props.question.isNotKnow;
|
|
|
@@ -183,6 +228,9 @@ const handleSelect = (option: Study.QuestionOption) => {
|
|
|
changeQuestion();
|
|
|
}
|
|
|
}
|
|
|
+const handleSubQuestionClick = (index: number) => {
|
|
|
+ emit('changeSubQuestion', index);
|
|
|
+}
|
|
|
const handleSubQuestionUpdate = (question: Study.Question) => {
|
|
|
emit('update:question', question);
|
|
|
checkIsDone();
|
|
|
@@ -206,10 +254,14 @@ const handleSelectNotKnow = () => {
|
|
|
// 查找是否有子题没有做,有的话就自动滚动到目标处
|
|
|
const findNotDoneSubQuestion = () => {
|
|
|
const notDoneSubQuestion = props.question.subQuestions.find(q => !q.isDone);
|
|
|
+ console.log(notDoneSubQuestion)
|
|
|
if (notDoneSubQuestion) {
|
|
|
const selector = `qs_${notDoneSubQuestion.id}`;
|
|
|
// 通知父组件滚动
|
|
|
- emit('scrollTo', selector);
|
|
|
+ // emit('scrollTo', selector);
|
|
|
+ if (notDoneSubQuestion.subIndex !== undefined) {
|
|
|
+ emit('changeSubQuestion', notDoneSubQuestion.subIndex);
|
|
|
+ }
|
|
|
} else {
|
|
|
// 否则切换到下一题
|
|
|
changeQuestion();
|
|
|
@@ -284,7 +336,7 @@ const isSelected = (option: Study.QuestionOption) => {
|
|
|
}
|
|
|
|
|
|
.question-content {
|
|
|
- @apply text-32 text-fore-title;
|
|
|
+ @apply text-32 text-fore-title break-words;
|
|
|
}
|
|
|
|
|
|
.question-options {
|
|
|
@@ -297,7 +349,7 @@ const isSelected = (option: Study.QuestionOption) => {
|
|
|
}
|
|
|
|
|
|
.question-option-content {
|
|
|
- @apply text-28 text-fore-title ml-20;
|
|
|
+ @apply text-28 text-fore-title ml-20 flex-1 min-w-0;
|
|
|
}
|
|
|
}
|
|
|
|