123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- <!-- eslint-disable vue/no-v-html -->
- <template>
- <div class="dialogue-preview">
- <div class="stem">
- <span class="question-number" :style="{ fontSize: data.property.stem_question_number_font_size }">
- {{ questionNumberEndIsBracket(data.property.question_number) }}
- </span>
- <span v-html="sanitizeHTML(data.stem)"></span>
- </div>
- <div
- v-if="isEnable(data.property.is_enable_description)"
- class="description rich-text"
- v-html="sanitizeHTML(data.description)"
- ></div>
- <div class="content">
- <div
- v-for="(item, i) in optionList"
- :key="i"
- class="option-list"
- :style="{ flexDirection: item.type === 'input' ? 'row-reverse' : 'row' }"
- >
- <span
- class="avatar"
- :style="{
- backgroundColor: data.property.role_list?.find(({ mark }) => mark === item.role).color,
- }"
- >
- {{ data.property.role_list?.find(({ mark }) => mark === item.role).name }}
- </span>
- <div v-if="item.type === 'text'" class="text-wrapper">
- <div class="text">{{ item.text }}</div>
- </div>
- <div v-else-if="item.type === 'image'" class="image">
- <img :src="file_map_list[item.file_id]" />
- </div>
- <div v-else-if="item.type === 'audio'" class="audio">
- <AudioPlay
- :file-id="item.file_id"
- :show-slider="true"
- :show-progress="false"
- :background-color="data.property.role_list?.find(({ mark }) => mark === item.role).color"
- />
- </div>
- <div v-else-if="item.type === 'input'">
- <SoundRecordPreview :wav-blob.sync="item.file_id" :disabled="disabled" type="small" />
- </div>
- </div>
- </div>
- <div v-if="isEnable(data.property.is_enable_reference_answer) && isShowRightAnswer" class="reference-box">
- <h5 class="reference-title">参考答案</h5>
- <span class="reference-answer rich-text" v-html="sanitizeHTML(data.reference_answer)"></span>
- </div>
- <div v-if="isEnable(data.property.is_enable_analysis) && isShowRightAnswer" class="analysis">
- <span class="analysis-title">解析</span>
- <div class="analysis-content" v-html="sanitizeHTML(data.analysis)"></div>
- </div>
- </div>
- </template>
- <script>
- import PreviewMixin from './components/PreviewMixin';
- import SoundRecordPreview from './components/common/SoundRecordPreview.vue';
- import { GetFileURLMap } from '@/api/app';
- export default {
- name: 'DialoguePreview',
- components: {
- SoundRecordPreview,
- },
- mixins: [PreviewMixin],
- data() {
- return {
- optionList: [],
- file_map_list: [],
- inputFocus: false,
- focusPostion: {
- i: -1,
- j: -1,
- },
- };
- },
- watch: {
- 'data.option_list': {
- handler(val) {
- let list = JSON.parse(JSON.stringify(val));
- let file_id_list = [];
- list.forEach(({ type, file_id }) => {
- if (type === 'image' || type === 'audio') {
- file_id_list.push(file_id);
- }
- });
- GetFileURLMap({ file_id_list }).then(({ url_map }) => {
- this.file_map_list = url_map;
- });
- this.optionList = list;
- },
- deep: true,
- immediate: true,
- },
- optionList: {
- handler(val) {
- this.answer.answer_list = [];
- val.forEach(({ type, mark, file_id }) => {
- if (type === 'input') {
- if (file_id.length <= 0) return;
- this.answer.answer_list.push({
- audio_file_id: file_id,
- mark,
- });
- return;
- }
- });
- },
- deep: true,
- immediate: true,
- },
- isJudgingRightWrong(val) {
- if (!val) return;
- this.answer.answer_list.forEach(({ mark, audio_file_id }) => {
- let findOption = this.optionList.find((item) => item.mark === mark);
- findOption.file_id = audio_file_id;
- });
- },
- },
- methods: {},
- };
- </script>
- <style lang="scss" scoped>
- @use '@/styles/mixin.scss' as *;
- .dialogue-preview {
- @include preview;
- .description {
- display: flex;
- flex-wrap: wrap;
- gap: 4px 8px;
- &-item {
- padding: 4px 8px;
- cursor: pointer;
- background-color: #e9edf7;
- border-radius: 4px;
- &:hover,
- &:active {
- color: $light-main-color;
- }
- }
- }
- .content {
- display: flex;
- flex-direction: column;
- row-gap: 16px;
- padding: 24px;
- background-color: $fill-color;
- border-radius: 16px;
- .option-list {
- display: flex;
- column-gap: 8px;
- .avatar {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 40px;
- min-width: 40px;
- height: 40px;
- min-height: 40px;
- margin-right: 8px;
- font-size: 12px;
- color: #fff;
- border-radius: 50%;
- }
- .text-wrapper {
- display: flex;
- flex-direction: column;
- row-gap: 8px;
- align-items: flex-start;
- .text {
- padding: 8px 12px;
- font-size: 16px;
- word-break: break-all;
- background-color: #fff;
- border-radius: 8px;
- .el-input {
- display: inline-flex;
- align-items: center;
- width: 120px;
- margin: 0 2px;
- &.right {
- :deep input.el-input__inner {
- color: $right-color;
- }
- }
- &.wrong {
- :deep input.el-input__inner {
- color: $error-color;
- }
- }
- & + .right-answer {
- position: relative;
- left: -4px;
- display: inline-block;
- height: 32px;
- font-size: 16px;
- line-height: 28px;
- vertical-align: bottom;
- border-bottom: 1px solid $font-color;
- }
- :deep input.el-input__inner {
- padding: 0;
- font-size: 16px;
- color: $font-color;
- text-align: center;
- background-color: #fff;
- border-width: 0;
- border-bottom: 1px solid $font-color;
- border-radius: 0;
- }
- }
- }
- }
- .sound-record-preview {
- padding: 4px;
- background-color: #fff;
- border-radius: 40px;
- :deep .sound-item .sound-item-span {
- color: #1d1d1d;
- background-color: #fff;
- }
- :deep .sound-item-luyin .sound-item-span {
- color: #fff;
- background-color: $light-main-color;
- }
- }
- .image img {
- border-radius: 8px;
- }
- }
- }
- }
- </style>
|