修改练习的问答题答题
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<view class="analysis_div" @click.stop="click_option()" :class="status">
|
||||
<view class="line">
|
||||
<text class="tr">维度评分:</text>
|
||||
<text class="td">{{ dimension_all_score }}</text>
|
||||
</view>
|
||||
<view class="line" v-for="item in evalSettingVos">
|
||||
<text class="tr">{{ item.gradeDimens }}:</text>
|
||||
<text class="td">{{ item.anlyGrade }}</text>
|
||||
<view class="your_answer" v-if="item.dimensCode==='01'">
|
||||
<rich-text :nodes="highlightedText" class="content" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, nextTick, computed, toRaw, watch } from 'vue';
|
||||
const emit = defineEmits(['click_option']);
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
required: false
|
||||
},
|
||||
judgeResult: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
},
|
||||
answerText: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
}
|
||||
});
|
||||
const evalSettingVos = computed(() => props.value.evalSettingVos);
|
||||
const status = computed(() => (props.judgeResult ? 'success' : 'error'));
|
||||
const keywords = computed(() => {
|
||||
if (!props.value.relKeyword) return [];
|
||||
return props.value.relKeyword.split(',').map(key => key.trim());
|
||||
});
|
||||
|
||||
const highlightedText = computed(() => {
|
||||
// 如果没有关键词,直接返回原文本
|
||||
if (!keywords.value.length) return props.answerText;
|
||||
// 构建正则表达式,匹配所有关键词(不区分大小写)
|
||||
// 对关键词进行转义,避免特殊字符影响正则
|
||||
const escapedKeywords = keywords.value.map(keyword =>
|
||||
keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
);
|
||||
|
||||
// 创建正则表达式,g表示全局匹配,i表示不区分大小写
|
||||
const regex = new RegExp(`(${escapedKeywords.join('|')})`, 'gi');
|
||||
|
||||
// 替换匹配到的关键词,用span包裹并添加高亮样式
|
||||
return props.answerText.replace(regex, (match) =>
|
||||
`<span class="highlight">${match}</span>`
|
||||
);
|
||||
});
|
||||
const dimension_all_score = computed(() => {
|
||||
return (
|
||||
evalSettingVos.value
|
||||
// 先通过map提取每个item的anlyGrade,不存在或非数字则取0
|
||||
.map((item) => (item?.anlyGrade && typeof item.anlyGrade === 'number' ? item.anlyGrade : 0))
|
||||
// 再通过reduce累加所有数值
|
||||
.reduce((total, current) => total + current, 0)
|
||||
);
|
||||
});
|
||||
watch(evalSettingVos.value, (newVal) => {
|
||||
console.log('newVal2', newVal);
|
||||
});
|
||||
const click_option = () => {
|
||||
emit('click_option', props.analysisVo);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.success {
|
||||
background-color: #e7f8ed;
|
||||
.td {
|
||||
color: #15b859;
|
||||
}
|
||||
:deep(.highlight) {
|
||||
color: #15b859;
|
||||
}
|
||||
}
|
||||
.error {
|
||||
background-color: #fce8e9;
|
||||
.td {
|
||||
color: #f5212d;
|
||||
}
|
||||
:deep(.highlight) {
|
||||
color: #f5212d;
|
||||
}
|
||||
}
|
||||
.your_answer{
|
||||
:deep(.highlight) {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.analysis_div {
|
||||
margin-top: 30rpx;
|
||||
|
||||
border-radius: 16rpx;
|
||||
padding: 22rpx 15rpx 15rpx 34rpx;
|
||||
.line {
|
||||
margin: 12rpx 0;
|
||||
}
|
||||
.tr {
|
||||
font-weight: 600;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.td {
|
||||
font-weight: 600;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.your_answer{
|
||||
font-weight: 500;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
text-align: left;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,57 +1,63 @@
|
||||
<template>
|
||||
<view class="talking-info" v-if="status === '02'">
|
||||
<view :class="['talking-gif', isPlaying ? 'is-play' : '']">
|
||||
<!-- <CommonLoading color="#fff" /> -->
|
||||
<view class="talking-line">
|
||||
<view class="talking-info" v-if="status === '02'">
|
||||
<view :class="['talking-gif', isPlaying ? 'is-play' : '']">
|
||||
<!-- <CommonLoading color="#fff" /> -->
|
||||
</view>
|
||||
<view class="right-time">{{ voiceTime }}</view>
|
||||
<view class="talking-cont">
|
||||
<text :class="['talking-text translate-text loading']" v-show="textShow">
|
||||
{{ showContent }}
|
||||
</text>
|
||||
<view class="talking-text translate-text" v-if="textLoading">
|
||||
<CommonLoading color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="btns-cont">
|
||||
<view class="play-btn">
|
||||
<image
|
||||
v-show="!isPlaying"
|
||||
class="icon"
|
||||
@click="playVoice"
|
||||
src="@/static/images/course/play-blue.png"
|
||||
style="width: 100%; height: 100%"
|
||||
></image>
|
||||
<image
|
||||
v-show="isPlaying"
|
||||
class="icon"
|
||||
@click.stop="playVoice"
|
||||
src="@/static/images/course/stop-blue.png"
|
||||
style="width: 100%; height: 100%"
|
||||
></image>
|
||||
</view>
|
||||
<view class="text-btn" v-if="!textShow" @click.stop="translateVoice()">文</view>
|
||||
<view class="fl1"></view>
|
||||
<view v-show="!props.isPreview && props.button_again_show" class="btns-cont-button-text" @click.stop="buutton_click('again')">
|
||||
重答
|
||||
</view>
|
||||
<view v-show="!props.isPreview && props.button_complete_show" class="btns-cont-button-text" @click.stop="buutton_click('complete')">
|
||||
完成
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-time">{{ voiceTime }}</view>
|
||||
<view class="talking-cont">
|
||||
<text :class="['talking-text translate-text loading']" v-show="textShow">
|
||||
{{ showContent }}
|
||||
</text>
|
||||
<view class="talking-text translate-text" v-if="textLoading">
|
||||
<!-- 01纯文字 -->
|
||||
<view class="talking-info talking-info-text" v-else-if="status === '01'">
|
||||
<view class="talking-cont">
|
||||
<text :class="['talking-text translate-text loading']">
|
||||
{{ showContent }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="btns-cont" v-show="!props.isPreview">
|
||||
<view class="fl1"></view>
|
||||
<view v-if="props.button_again_show" class="btns-cont-button-text" @click.stop="buutton_click('again')">重答</view>
|
||||
<view v-if="props.button_complete_show" class="btns-cont-button-text" @click.stop="buutton_click('complete')">完成</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="talking-info talking-info-loading" v-else-if="status === '00'">
|
||||
<view :class="['talking-gif']">
|
||||
<CommonLoading color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="btns-cont">
|
||||
<view class="play-btn">
|
||||
<image
|
||||
v-show="!isPlaying"
|
||||
class="icon"
|
||||
@click="playVoice"
|
||||
src="@/static/images/course/play-blue.png"
|
||||
style="width: 100%; height: 100%"
|
||||
></image>
|
||||
<image
|
||||
v-show="isPlaying"
|
||||
class="icon"
|
||||
@click.stop="playVoice"
|
||||
src="@/static/images/course/stop-blue.png"
|
||||
style="width: 100%; height: 100%"
|
||||
></image>
|
||||
</view>
|
||||
<view class="text-btn" v-if="!textShow" @click.stop="translateVoice()">文</view>
|
||||
<view class="fl1"></view>
|
||||
<view class="btns-cont-button-text" @click.stop="buutton_click('again')">重答</view>
|
||||
<view class="btns-cont-button-text" @click.stop="buutton_click('complete')">完成</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 01纯文字 -->
|
||||
<view class="talking-info talking-info-text" v-else-if="status === '01'">
|
||||
<view class="talking-cont">
|
||||
<text :class="['talking-text translate-text loading']">
|
||||
{{ showContent }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="btns-cont">
|
||||
<view class="fl1"></view>
|
||||
<view class="btns-cont-button-text" @click.stop="buutton_click('again')">重答</view>
|
||||
<view class="btns-cont-button-text" @click.stop="buutton_click('complete')">完成</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="talking-info talking-info-loading" v-else-if="status === '00'">
|
||||
<view :class="['talking-gif']">
|
||||
<CommonLoading color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -85,12 +91,23 @@
|
||||
default: '',
|
||||
type: String
|
||||
},
|
||||
isPreview: { // 是否是预览语音
|
||||
isPreview: {
|
||||
// 是否是预览语音
|
||||
default: false,
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
button_again_show: {
|
||||
// 是否显示重答按钮
|
||||
default: true,
|
||||
type: Boolean
|
||||
},
|
||||
button_complete_show: {
|
||||
// 是否显示重答按钮
|
||||
default: true,
|
||||
type: Boolean
|
||||
},
|
||||
});
|
||||
|
||||
console.log('props.isPreview', props.isPreview);
|
||||
const audioStore = useAudioStore();
|
||||
const { dataInfo } = toRefs(props);
|
||||
const status = computed(() => props.status);
|
||||
@@ -139,7 +156,7 @@
|
||||
console.log('点击播放');
|
||||
audioStore.playAudio();
|
||||
};
|
||||
let unsubscribe = () =>{};
|
||||
let unsubscribe = () => {};
|
||||
onMounted(() => {
|
||||
// 2. 监听 Store 中 isPlaying 的变化,实时同步
|
||||
unsubscribe = audioStore.$subscribe((mutation, state) => {
|
||||
@@ -174,12 +191,16 @@
|
||||
audioStore.stopAudio();
|
||||
// 2. 移除当前组件注册的回调(避免内存泄漏)
|
||||
audioStore.removeCallbacks();
|
||||
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.talking-line {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.talking-info {
|
||||
padding: 20rpx;
|
||||
border-radius: 15rpx;
|
||||
@@ -188,7 +209,6 @@
|
||||
position: relative;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
float: right;
|
||||
|
||||
.talking-gif {
|
||||
width: 200rpx;
|
||||
@@ -220,14 +240,14 @@
|
||||
padding-bottom: 20rpx;
|
||||
width: auto;
|
||||
min-width: calc(100vw * 0.45);
|
||||
float: right;
|
||||
// float: right;
|
||||
.talking-cont {
|
||||
margin-top: 0rpx;
|
||||
// margin-top: 0rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.talking-cont {
|
||||
margin-top: 16rpx;
|
||||
// margin-top: 16rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.talking-text {
|
||||
@@ -251,7 +271,7 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 20rpx;
|
||||
margin-top: 22rpx;
|
||||
margin-top: 14rpx;
|
||||
.replay-btn {
|
||||
float: left;
|
||||
width: 46rpx;
|
||||
@@ -321,7 +341,7 @@
|
||||
line-height: 30rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-left: 10rpx;
|
||||
margin-left: 18rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
:isPreview="props.isPreview"
|
||||
:activeVoiceId="subject_data.qnsId"
|
||||
@buutton_click="questionButtonClick"
|
||||
:button_complete_show="props.mode === 'practice'"
|
||||
></questionVue>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -62,17 +63,31 @@
|
||||
确定
|
||||
</uv-button>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="analysis_div"
|
||||
v-if="!clearResult && ['study', 'mistake', 'settlement', 'practice'].includes(props.mode)"
|
||||
>
|
||||
<view class="analysis_title">
|
||||
<view class="analysis_title" v-if="qnsTyp !== 'ES'">
|
||||
<view class="success_answer">正确答案:{{ correctResultLabel.join('') }}</view>
|
||||
<view class="your_answer">
|
||||
你的答案:
|
||||
<text :class="right_or_wrong_class ? 'success' : 'error'">{{ myResultLabel.join('') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<esAnalysis
|
||||
v-if="qnsTyp === 'ES'"
|
||||
:value="subject_data.itemVos[0]"
|
||||
:judgeResult="judgeResultStatus"
|
||||
:answerText="subject_data.anserResult"
|
||||
></esAnalysis>
|
||||
|
||||
<!-- 问答题专属参考答案 -->
|
||||
<view class="reference_answer" v-if="qnsTyp === 'ES'">
|
||||
<view class="reference_answer_title">参考答案:</view>
|
||||
{{ subject_data.itemVos[0]?.itemAnswer ?? '' }}
|
||||
</view>
|
||||
|
||||
<view class="analysis_note">题目解析:{{ subject_data?.analyContent }}</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -82,6 +97,7 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, nextTick, computed, getCurrentInstance } from 'vue';
|
||||
import radioSubjectItem from './radio-subject-item.vue';
|
||||
import esAnalysis from './es-analysis.vue';
|
||||
import questionVue from './question.vue';
|
||||
import { markIcon, feedbackIcon } from '@/common/imgSvg';
|
||||
import { SUBJECT_TYPE } from '@/enum.js';
|
||||
@@ -132,7 +148,7 @@
|
||||
const isExpanded = ref(false);
|
||||
const wrapperRef = ref(null);
|
||||
const contentRef = ref(null);
|
||||
|
||||
const judgeResultStatus = computed(() => props.item.judgeResult === 'P');
|
||||
const animationStyle = ref({
|
||||
height: '0px',
|
||||
overflow: 'hidden',
|
||||
@@ -271,14 +287,7 @@
|
||||
};
|
||||
|
||||
// 初始化动画
|
||||
onMounted(() => {
|
||||
// // 创建动画实例
|
||||
// animation = uni.createAnimation({
|
||||
// duration: 300,
|
||||
// timingFunction: 'ease-in-out',
|
||||
// delay: 0
|
||||
// });
|
||||
});
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -318,7 +327,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 32rpx 0 28rpx 0;
|
||||
margin: 32rpx 0 0 0;
|
||||
|
||||
.success_answer {
|
||||
}
|
||||
@@ -341,6 +350,22 @@
|
||||
line-height: 48rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
margin-top: 28rpx;
|
||||
}
|
||||
.reference_answer {
|
||||
.reference_answer_title {
|
||||
font-weight: 700;
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
text-align: left;
|
||||
line-height: 30rpx;
|
||||
margin: 30rpx 0;
|
||||
}
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #666666;
|
||||
line-height: 48rpx;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.item {
|
||||
|
||||
Reference in New Issue
Block a user