|  | @@ -57,16 +57,61 @@
 | 
	
		
			
				|  |  |                        :class="[index === 0 ? 'pinyin-text-left' : '']"
 | 
	
		
			
				|  |  |                      >
 | 
	
		
			
				|  |  |                        <template v-if="item.type === 'input'">
 | 
	
		
			
				|  |  | -                        <el-input
 | 
	
		
			
				|  |  | -                          :key="index"
 | 
	
		
			
				|  |  | -                          v-model="item.value"
 | 
	
		
			
				|  |  | -                          :disabled="disabled"
 | 
	
		
			
				|  |  | -                          :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | -                        />
 | 
	
		
			
				|  |  | +                        <template v-if="data.property.fill_type === fillTypeList[0].value">
 | 
	
		
			
				|  |  | +                          <el-input
 | 
	
		
			
				|  |  | +                            :key="index"
 | 
	
		
			
				|  |  | +                            v-model="item.value"
 | 
	
		
			
				|  |  | +                            :disabled="disabled"
 | 
	
		
			
				|  |  | +                            :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | +                          />
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[1].value">
 | 
	
		
			
				|  |  | +                          <el-popover :key="index" placement="top" trigger="click">
 | 
	
		
			
				|  |  | +                            <div class="word-list">
 | 
	
		
			
				|  |  | +                              <span
 | 
	
		
			
				|  |  | +                                v-for="{ content, mark } in data.word_list"
 | 
	
		
			
				|  |  | +                                :key="mark"
 | 
	
		
			
				|  |  | +                                class="word-item"
 | 
	
		
			
				|  |  | +                                @click="handleSelectWord(content, mark, item)"
 | 
	
		
			
				|  |  | +                              >
 | 
	
		
			
				|  |  | +                                {{ content }}
 | 
	
		
			
				|  |  | +                              </span>
 | 
	
		
			
				|  |  | +                            </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            <el-input
 | 
	
		
			
				|  |  | +                              slot="reference"
 | 
	
		
			
				|  |  | +                              v-model="item.value"
 | 
	
		
			
				|  |  | +                              :readonly="true"
 | 
	
		
			
				|  |  | +                              :class="[data.property.fill_font, ...computedAnswerClass(item.mark)]"
 | 
	
		
			
				|  |  | +                              :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </el-popover>
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[2].value">
 | 
	
		
			
				|  |  | +                          <span :key="j" class="write-click" @click="handleWriteClick(item)">
 | 
	
		
			
				|  |  | +                            <img
 | 
	
		
			
				|  |  | +                              v-show="item.write_base64"
 | 
	
		
			
				|  |  | +                              style="background-color: #f4f4f4"
 | 
	
		
			
				|  |  | +                              :src="item.write_base64"
 | 
	
		
			
				|  |  | +                              alt="write-show"
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </span>
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[3].value">
 | 
	
		
			
				|  |  | +                          <SoundRecordBox
 | 
	
		
			
				|  |  | +                            ref="record"
 | 
	
		
			
				|  |  | +                            :key="j"
 | 
	
		
			
				|  |  | +                            type="mini"
 | 
	
		
			
				|  |  | +                            :many-times="false"
 | 
	
		
			
				|  |  | +                            class="record-box"
 | 
	
		
			
				|  |  | +                            :answer-record-list="data.audio_answer_list"
 | 
	
		
			
				|  |  | +                            :task-model="isJudgingRightWrong ? 'ANSWER' : ''"
 | 
	
		
			
				|  |  | +                            @handleWav="handleMiniWav($event, item)"
 | 
	
		
			
				|  |  | +                          />
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  |                          <span v-if="data.property.pinyin_position === 'bottom'" class="pinyin"> </span>
 | 
	
		
			
				|  |  | -                        <!-- <span v-show="computedAnswerText(li.mark).length > 0" :key="`answer-${indexs}`" class="right-answer">
 | 
	
		
			
				|  |  | -                {{ computedAnswerText(li.mark) }}
 | 
	
		
			
				|  |  | -              </span> -->
 | 
	
		
			
				|  |  |                        </template>
 | 
	
		
			
				|  |  |                        <template v-else>
 | 
	
		
			
				|  |  |                          <span v-if="data.property.pinyin_position === 'top'" class="pinyin">
 | 
	
	
		
			
				|  | @@ -85,12 +130,60 @@
 | 
	
		
			
				|  |  |                      <p v-for="(item, index) in col.model_essay" :key="index">
 | 
	
		
			
				|  |  |                        <span v-if="item.type === 'text'" :key="index" v-html="sanitizeHTML(item.value)"></span>
 | 
	
		
			
				|  |  |                        <template v-if="item.type === 'input'">
 | 
	
		
			
				|  |  | -                        <el-input
 | 
	
		
			
				|  |  | -                          :key="index"
 | 
	
		
			
				|  |  | -                          v-model="item.value"
 | 
	
		
			
				|  |  | -                          :disabled="disabled"
 | 
	
		
			
				|  |  | -                          :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | -                        />
 | 
	
		
			
				|  |  | +                        <template v-if="data.property.fill_type === fillTypeList[0].value">
 | 
	
		
			
				|  |  | +                          <el-input
 | 
	
		
			
				|  |  | +                            :key="index"
 | 
	
		
			
				|  |  | +                            v-model="item.value"
 | 
	
		
			
				|  |  | +                            :disabled="disabled"
 | 
	
		
			
				|  |  | +                            :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | +                          />
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[1].value">
 | 
	
		
			
				|  |  | +                          <el-popover :key="index" placement="top" trigger="click">
 | 
	
		
			
				|  |  | +                            <div class="word-list">
 | 
	
		
			
				|  |  | +                              <span
 | 
	
		
			
				|  |  | +                                v-for="{ content, mark } in data.word_list"
 | 
	
		
			
				|  |  | +                                :key="mark"
 | 
	
		
			
				|  |  | +                                class="word-item"
 | 
	
		
			
				|  |  | +                                @click="handleSelectWord(content, mark, item)"
 | 
	
		
			
				|  |  | +                              >
 | 
	
		
			
				|  |  | +                                {{ content }}
 | 
	
		
			
				|  |  | +                              </span>
 | 
	
		
			
				|  |  | +                            </div>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            <el-input
 | 
	
		
			
				|  |  | +                              slot="reference"
 | 
	
		
			
				|  |  | +                              v-model="item.value"
 | 
	
		
			
				|  |  | +                              :readonly="true"
 | 
	
		
			
				|  |  | +                              :class="[data.property.fill_font, ...computedAnswerClass(item.mark)]"
 | 
	
		
			
				|  |  | +                              :style="[{ width: Math.max(80, item.value.length * 21.3) + 'px' }]"
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </el-popover>
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[2].value">
 | 
	
		
			
				|  |  | +                          <span :key="j" class="write-click" @click="handleWriteClick(item)">
 | 
	
		
			
				|  |  | +                            <img
 | 
	
		
			
				|  |  | +                              v-show="item.write_base64"
 | 
	
		
			
				|  |  | +                              style="background-color: #f4f4f4"
 | 
	
		
			
				|  |  | +                              :src="item.write_base64"
 | 
	
		
			
				|  |  | +                              alt="write-show"
 | 
	
		
			
				|  |  | +                            />
 | 
	
		
			
				|  |  | +                          </span>
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        <template v-else-if="data.property.fill_type === fillTypeList[3].value">
 | 
	
		
			
				|  |  | +                          <SoundRecordBox
 | 
	
		
			
				|  |  | +                            ref="record"
 | 
	
		
			
				|  |  | +                            :key="j"
 | 
	
		
			
				|  |  | +                            type="mini"
 | 
	
		
			
				|  |  | +                            :many-times="false"
 | 
	
		
			
				|  |  | +                            class="record-box"
 | 
	
		
			
				|  |  | +                            :answer-record-list="data.audio_answer_list"
 | 
	
		
			
				|  |  | +                            :task-model="isJudgingRightWrong ? 'ANSWER' : ''"
 | 
	
		
			
				|  |  | +                            @handleWav="handleMiniWav($event, item)"
 | 
	
		
			
				|  |  | +                          />
 | 
	
		
			
				|  |  | +                        </template>
 | 
	
		
			
				|  |  |                          <!-- <span v-show="computedAnswerText(li.mark).length > 0" :key="`answer-${indexs}`" class="right-answer">
 | 
	
		
			
				|  |  |                  {{ computedAnswerText(li.mark) }}
 | 
	
		
			
				|  |  |                </span> -->
 | 
	
	
		
			
				|  | @@ -113,24 +206,30 @@
 | 
	
		
			
				|  |  |          </table>
 | 
	
		
			
				|  |  |        </div>
 | 
	
		
			
				|  |  |      </div>
 | 
	
		
			
				|  |  | +    <WriteDialog :visible.sync="writeVisible" @confirm="handleWriteConfirm" />
 | 
	
		
			
				|  |  |    </div>
 | 
	
		
			
				|  |  |  </template>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  <script>
 | 
	
		
			
				|  |  | -import { getTableData } from '@/views/book/courseware/data/table';
 | 
	
		
			
				|  |  | +import { getTableData, fillTypeList } from '@/views/book/courseware/data/table';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import PreviewMixin from '../common/PreviewMixin';
 | 
	
		
			
				|  |  | -import { isEnable } from '../../../data/common';
 | 
	
		
			
				|  |  | +import WriteDialog from '../fill/components/WriteDialog.vue';
 | 
	
		
			
				|  |  | +import SoundRecordBox from '@/views/book/courseware/preview/components/record_input/SoundRecord.vue';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  export default {
 | 
	
		
			
				|  |  |    name: 'TablePreview',
 | 
	
		
			
				|  |  | -  components: {},
 | 
	
		
			
				|  |  | +  components: { SoundRecordBox, WriteDialog },
 | 
	
		
			
				|  |  |    mixins: [PreviewMixin],
 | 
	
		
			
				|  |  |    data() {
 | 
	
		
			
				|  |  |      return {
 | 
	
		
			
				|  |  |        data: getTableData(),
 | 
	
		
			
				|  |  |        table_width: 0,
 | 
	
		
			
				|  |  |        multilingualTextList: {}, // 多语言对应的切割后的翻译
 | 
	
		
			
				|  |  | +      fillTypeList,
 | 
	
		
			
				|  |  | +      selectedWordList: [], // 用于存储选中的词汇
 | 
	
		
			
				|  |  | +      writeVisible: false,
 | 
	
		
			
				|  |  | +      writeMark: '',
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    computed: {
 | 
	
	
		
			
				|  | @@ -186,7 +285,6 @@ export default {
 | 
	
		
			
				|  |  |            this.$set(this.multilingualTextList, item.type, chunkedArr);
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      console.log(this.data);
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      computedAnswerText(mark) {
 | 
	
		
			
				|  |  |        if (!this.isShowRightAnswer) return '';
 | 
	
	
		
			
				|  | @@ -199,6 +297,65 @@ export default {
 | 
	
		
			
				|  |  |        if (isRight) return '';
 | 
	
		
			
				|  |  |        return `(${answerValue})`;
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 计算答题对错选项字体颜色
 | 
	
		
			
				|  |  | +     * @param {string} mark 选项标识
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    computedAnswerClass(mark) {
 | 
	
		
			
				|  |  | +      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
 | 
	
		
			
				|  |  | +        return '';
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      let selectOption = this.answer.answer_list.find((item) => item.mark === mark);
 | 
	
		
			
				|  |  | +      let answerOption = this.data.answer.answer_list.find((item) => item.mark === mark);
 | 
	
		
			
				|  |  | +      if (!selectOption) return '';
 | 
	
		
			
				|  |  | +      let selectValue = selectOption.value;
 | 
	
		
			
				|  |  | +      let answerValue = answerOption.value;
 | 
	
		
			
				|  |  | +      let answerType = answerOption.type;
 | 
	
		
			
				|  |  | +      let classList = [];
 | 
	
		
			
				|  |  | +      let isRight =
 | 
	
		
			
				|  |  | +        answerType === 'only_one' ? selectValue === answerValue : answerValue.split('/').includes(selectValue);
 | 
	
		
			
				|  |  | +      if (this.isJudgingRightWrong) {
 | 
	
		
			
				|  |  | +        isRight ? classList.push('right') : classList.push('wrong');
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (this.isShowRightAnswer && !isRight) {
 | 
	
		
			
				|  |  | +        classList.push('show-right-answer');
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return classList;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 处理小音频录音
 | 
	
		
			
				|  |  | +     * @param {Object} data 音频数据
 | 
	
		
			
				|  |  | +     * @param {String} mark 选项标识
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    handleMiniWav(data, mark) {
 | 
	
		
			
				|  |  | +      if (!data || !mark) return;
 | 
	
		
			
				|  |  | +      this.$set(mark, 'audio_answer_list', data);
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 处理选中词汇
 | 
	
		
			
				|  |  | +     * @param {String} content 选中的词汇内容
 | 
	
		
			
				|  |  | +     * @param {String} mark 选项标识
 | 
	
		
			
				|  |  | +     * @param {Object} li 当前输入框对象
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    handleSelectWord(content, mark, li) {
 | 
	
		
			
				|  |  | +      if (!content || !mark || !li) return;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      li.value = content;
 | 
	
		
			
				|  |  | +      this.selectedWordList.push(mark);
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 处理书写区确认
 | 
	
		
			
				|  |  | +     * @param {String} data 书写区数据
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    handleWriteConfirm(data) {
 | 
	
		
			
				|  |  | +      if (!data) return;
 | 
	
		
			
				|  |  | +      this.$set(this.writeMark, 'write_base64', data);
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    handleWriteClick(mark) {
 | 
	
		
			
				|  |  | +      this.writeVisible = true;
 | 
	
		
			
				|  |  | +      this.writeMark = mark;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  </script>
 | 
	
	
		
			
				|  | @@ -234,6 +391,28 @@ $border-color: #e6e6e6;
 | 
	
		
			
				|  |  |          margin: 0;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +      .record-box {
 | 
	
		
			
				|  |  | +        display: inline-flex;
 | 
	
		
			
				|  |  | +        align-items: center;
 | 
	
		
			
				|  |  | +        background-color: #fff;
 | 
	
		
			
				|  |  | +        border-bottom: 1px solid $font-color;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      .write-click {
 | 
	
		
			
				|  |  | +        display: inline-block;
 | 
	
		
			
				|  |  | +        width: 104px;
 | 
	
		
			
				|  |  | +        height: 32px;
 | 
	
		
			
				|  |  | +        padding: 0 4px;
 | 
	
		
			
				|  |  | +        vertical-align: bottom;
 | 
	
		
			
				|  |  | +        cursor: pointer;
 | 
	
		
			
				|  |  | +        border-bottom: 1px solid $font-color;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        img {
 | 
	
		
			
				|  |  | +          width: 100%;
 | 
	
		
			
				|  |  | +          height: 100%;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |        .el-input {
 | 
	
		
			
				|  |  |          display: inline-flex;
 | 
	
		
			
				|  |  |          align-items: center;
 | 
	
	
		
			
				|  | @@ -276,7 +455,8 @@ $border-color: #e6e6e6;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          :deep input.el-input__inner {
 | 
	
		
			
				|  |  |            padding: 0;
 | 
	
		
			
				|  |  | -          font-size: 16pt;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // font-size: 16pt;
 | 
	
		
			
				|  |  |            color: $font-color;
 | 
	
		
			
				|  |  |            text-align: center;
 | 
	
		
			
				|  |  |            background-color: #fff;
 | 
	
	
		
			
				|  | @@ -302,13 +482,14 @@ $border-color: #e6e6e6;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        .pinyin {
 | 
	
		
			
				|  |  | +        height: 18px;
 | 
	
		
			
				|  |  |          font-family: 'League';
 | 
	
		
			
				|  |  |          font-size: 12px;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        &-left {
 | 
	
		
			
				|  |  |          span {
 | 
	
		
			
				|  |  | -          text-align: left;
 | 
	
		
			
				|  |  | +          // text-align: left;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 |