<!-- eslint-disable vue/no-v-html -->
<template>
  <div class="table-preview" :style="[getAreaStyle(), getComponentStyle()]">
    <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />

    <div class="main">
      <div
        class="table-box"
        :style="{
          width: isMobile ? '100%' : data.property.width + 'px',
        }"
      >
        <table style="width: 100%; table-layout: fixed">
          <colgroup>
            <col v-for="(item, i) in data.col_width" :key="`col-${i}`" :style="{ width: `${item.value}%` }" />
          </colgroup>
          <tr v-for="(row, i) in data.option_list" :key="`tr-${i}`" :style="{ height: data.property.height + 'px' }">
            <template v-for="(col, j) in row">
              <td
                v-if="col.is_show_cell"
                :key="col.mark"
                :colspan="col.cell.colspan"
                :rowspan="col.cell.rowspan"
                :style="{
                  borderTop: i === 0 ? '1px solid ' + data.property.border_color : '',
                  borderBottom: '1px solid ' + data.property.border_color,

                  borderLeft:
                    i === 0 && data.property.first_line_color
                      ? '1px solid ' + data.property.border_color
                      : j === 0
                        ? '2px solid ' +
                          (data.property.decoration_color ? data.property.decoration_color : data.property.border_color)
                        : '1px dotted ' + data.property.border_color,
                  borderRight:
                    i === 0 && data.property.first_line_color
                      ? '1px solid ' + data.property.border_color
                      : j === row.length - 1
                        ? '2px solid ' +
                          (data.property.decoration_color ? data.property.decoration_color : data.property.border_color)
                        : '1px dotted ' + data.property.border_color,
                  borderRadius: i === 0 && data.property.first_line_color ? '4px ' : '0',
                  background: col.cell.bgColor
                    ? col.cell.bgColor
                    : data.cols_bg_list[j]
                      ? data.cols_bg_list[j]
                      : data.rows_bg_list[i]
                        ? data.rows_bg_list[i]
                        : '',
                  height: data.property.height + 'px',
                }"
              >
                <div class="cell-wrap">
                  <div class="cell-wrap-content" :style="[tdStyle, computedRichStyle(col.content)]">
                    <template v-if="isEnable(data.property.view_pinyin)">
                      <template v-if="col.rich_text_list">
                        <div
                          v-for="(item, index) in col.rich_text_list"
                          :key="index"
                          class="pinyin-text pinyin-text-sentence"
                          :class="[
                            index === 0 ? 'pinyin-text-left' : '',
                            item.type === 'audio' ? 'pinyin-text-audio' : '',
                          ]"
                        >
                          <!-- 文字块：包含 word_list -->
                          <span
                            v-if="item.type === 'text'"
                            :key="'text-' + index"
                            class="pinyin-sentence"
                            :style="[
                              { 'align-items': data.property.pinyin_position === 'top' ? 'flex-end' : 'flex-start' },
                            ]"
                          >
                            <span
                              v-for="(word, wIndex) in item.word_list"
                              :key="wIndex"
                              class="pinyin-text"
                              :style="item.styleObj"
                            >
                              <span v-if="word.type === 'text'">
                                <span
                                  :style="{
                                    flexDirection:
                                      data.property.pinyin_position === 'top' ? 'column' : 'column-reverse',
                                    'align-items': getWordAlignItems(word, item),
                                  }"
                                >
                                  <span class="pinyin" :style="getPinyinStyle(word)"> {{ word.pinyin }}</span>
                                  <span class="py-char" :style="getCharStyle(word, item)">{{
                                    convertText(word.text)
                                  }}</span>
                                </span>
                              </span>
                              <template v-else-if="word.type === 'input'">
                                <span v-if="data.property.pinyin_position === 'top'" class="pinyin">&nbsp;</span>
                                <template v-if="data.property.fill_type === fillTypeList[0].value">
                                  <el-input
                                    :key="index"
                                    v-model="word.value"
                                    :disabled="disabled"
                                    :class="[...computedAnswerClass(word, i, j)]"
                                    :style="[{ width: Math.max(40, word.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, word)"
                                      >
                                        {{ convertText(content) }}
                                      </span>
                                    </div>

                                    <el-input
                                      slot="reference"
                                      v-model="word.value"
                                      :readonly="true"
                                      :class="[...computedAnswerClass(word, i, j)]"
                                      :style="[{ width: Math.max(40, word.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(word)">
                                    <img
                                      v-show="word.write_base64"
                                      style="background-color: #f4f4f4"
                                      :src="word.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' : ''"
                                    :attrib="data.unified_attrib"
                                    @handleWav="handleMiniWav($event, word)"
                                  />
                                </template>
                                <span v-if="data.property.pinyin_position === 'bottom'" class="pinyin">&nbsp;</span>
                              </template>
                            </span>
                          </span>
                          <!-- 图片块 -->
                          <div
                            v-else-if="item.type === 'image'"
                            :key="'image-' + index"
                            :style="item.containerStyle"
                            class="image-container"
                          >
                            <img
                              :src="item.src"
                              :alt="item.alt"
                              :width="item.width"
                              :height="item.height"
                              :style="item.imageStyle"
                              class="inline-image"
                            />
                          </div>
                          <!-- 视频块 -->
                          <div
                            v-else-if="item.type === 'video'"
                            :key="'video-' + index"
                            :style="item.containerStyle"
                            class="video-container"
                          >
                            <video
                              :poster="item.poster"
                              :width="item.width"
                              :height="item.height"
                              :style="item.mediaStyle"
                              controls
                              class="inline-video"
                            >
                              <source :src="item.src" :type="item.videoType" />
                              您的浏览器不支持视频播放
                            </video>
                          </div>
                          <!-- 音频块 -->
                          <div
                            v-else-if="item.type === 'audio'"
                            :key="'audio-' + index"
                            :style="item.containerStyle"
                            class="audio-container"
                          >
                            <audio :src="item.src" :style="item.mediaStyle" controls class="inline-audio">
                              您的浏览器不支持音频播放
                            </audio>
                          </div>
                          <!-- 换行符 -->
                          <br v-else-if="item.type === 'newline'" :key="'newline-' + index" />

                          <!--
                        <template v-else>
                          <span v-if="data.property.pinyin_position === 'top'" class="pinyin">
                            {{ item.pinyin.replace(/\s+/g, '') }}
                          </span>
                          <span :style="{ ...item.activeTextStyle }">
                            {{ convertText(item.text) }}
                          </span>
                          <span v-if="data.property.pinyin_position === 'bottom'" class="pinyin">{{
                            item.pinyin.replace(/\s+/g, '')
                          }}</span>
                        </template> -->
                        </div>
                      </template>
                    </template>
                    <template v-else>
                      <div v-for="(item, index) in col.model_essay" :key="index" :style="[tdStyle]">
                        <span
                          v-if="item.type === 'text'"
                          :key="index"
                          :style="{
                            fontSize:
                              data.unified_attrib && data.unified_attrib.font_size ? data.unified_attrib.font_size : '',
                            fontFamily: data.unified_attrib && data.unified_attrib.font ? data.unified_attrib.font : '',
                          }"
                          v-html="convertText(sanitizeHTML(item.value))"
                        ></span>
                        <template v-if="item.type === 'input'">
                          <template v-if="data.property.fill_type === fillTypeList[0].value">
                            <el-input
                              :key="index"
                              v-model="item.value"
                              :disabled="disabled"
                              :class="[...computedAnswerClass(item, i, j)]"
                              :style="[{ width: Math.max(40, 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)"
                                >
                                  {{ convertText(content) }}
                                </span>
                              </div>

                              <el-input
                                slot="reference"
                                v-model="item.value"
                                :readonly="true"
                                :class="[...computedAnswerClass(item, i, j)]"
                                :style="[{ width: Math.max(40, 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' : ''"
                              :attrib="data.unified_attrib"
                              @handleWav="handleMiniWav($event, item)"
                            />
                          </template>
                        </template>
                      </div>
                    </template>
                  </div>

                  <i
                    v-if="col.cell.isCross"
                    :class="[
                      { 'el-icon-check': col.crossAnswer === statusList[1] },
                      { 'el-icon-close': col.crossAnswer === statusList[2] },
                      ...computedAnswerCrossClass(col, i, j),
                    ]"
                    :style="{ display: 'block', width: '18px', height: '18px', border: '1px solid #000' }"
                    @click="toggle(col)"
                  ></i>
                </div>
                <span v-if="showLang" class="multilingual" :style="[tdStyle, computedRichStyle(col.content)]">
                  {{
                    multilingualTextList[getLang()] &&
                    multilingualTextList[getLang()][i] &&
                    multilingualTextList[getLang()][i][j]
                      ? multilingualTextList[getLang()][i][j]
                      : ''
                  }}
                </span>
              </td>
            </template>
          </tr>
        </table>
      </div>
      <PreviewOperation
        v-if="isHasInput"
        @showAnswerAnalysis="showAnswerAnalysis"
        @judgeCorrect="judgeCorrect"
        @retry="retry"
      />
      <AnswerCorrect
        :answer-correct="data?.answer_correct"
        :visible.sync="visibleAnswerCorrect"
        :is-check-correct="isCheckCorrect"
        @closeAnswerCorrect="closeAnswerCorrect"
      />
      <AnswerAnalysis
        :visible.sync="visibleAnswerAnalysis"
        :answer-list="data.answer_list"
        :analysis-list="data.analysis_list"
        @closeAnswerAnalysis="closeAnswerAnalysis"
      >
        <div
          slot="right-answer"
          class="table-box"
          :style="{
            width: isMobile ? '100%' : data.property.width + 'px',
          }"
        >
          <table style="width: 100%; table-layout: fixed">
            <colgroup>
              <col v-for="(item, i) in data.col_width" :key="`col-${i}`" :style="{ width: `${item.value}%` }" />
            </colgroup>
            <tr v-for="(row, i) in data.option_list" :key="`tr-${i}`" :style="{ height: data.property.height + 'px' }">
              <template v-for="(col, j) in row">
                <td
                  v-if="col.is_show_cell"
                  :key="col.mark"
                  :colspan="col.colspan"
                  :rowspan="col.rowspan"
                  :style="{
                    borderTop: i === 0 ? '1px solid ' + data.property.border_color : '',
                    borderBottom: '1px solid ' + data.property.border_color,

                    borderLeft:
                      i === 0 && data.property.first_line_color
                        ? '1px solid ' + data.property.border_color
                        : j === 0
                          ? '2px solid ' +
                            (data.property.decoration_color
                              ? data.property.decoration_color
                              : data.property.border_color)
                          : '1px dotted ' + data.property.border_color,
                    borderRight:
                      i === 0 && data.property.first_line_color
                        ? '1px solid ' + data.property.border_color
                        : j === row.length - 1
                          ? '2px solid ' +
                            (data.property.decoration_color
                              ? data.property.decoration_color
                              : data.property.border_color)
                          : '1px dotted ' + data.property.border_color,
                    borderRadius: i === 0 && data.property.first_line_color ? '4px ' : '0',
                    background: col.cell.bgColor
                      ? col.cell.bgColor
                      : data.cols_bg_list[j]
                        ? data.cols_bg_list[j]
                        : data.rows_bg_list[i]
                          ? data.rows_bg_list[i]
                          : '',
                    height: data.property.height + 'px',
                  }"
                >
                  <div class="cell-wrap">
                    <div class="cell-wrap-content" :style="[tdStyle, computedRichStyle(col.content)]">
                      <template v-if="isEnable(data.property.view_pinyin)">
                        <template v-if="col.rich_text_list">
                          <div
                            v-for="(item, index) in col.rich_text_list"
                            :key="index"
                            class="pinyin-text pinyin-text-sentence"
                            :class="[
                              index === 0 ? 'pinyin-text-left' : '',
                              item.type === 'audio' ? 'pinyin-text-audio' : '',
                            ]"
                          >
                            <!-- 文字块：包含 word_list -->
                            <span
                              v-if="item.type === 'text'"
                              :key="'text-' + index"
                              class="pinyin-sentence"
                              :style="[
                                { 'align-items': data.property.pinyin_position === 'top' ? 'flex-end' : 'flex-start' },
                              ]"
                            >
                              <span
                                v-for="(word, wIndex) in item.word_list"
                                :key="wIndex"
                                class="pinyin-text"
                                :style="item.styleObj"
                              >
                                <span v-if="word.type === 'text'">
                                  <span
                                    :style="{
                                      flexDirection:
                                        data.property.pinyin_position === 'top' ? 'column' : 'column-reverse',
                                      'align-items': getWordAlignItems(word, item),
                                    }"
                                  >
                                    <span class="pinyin" :style="getPinyinStyle(word)"> {{ word.pinyin }}</span>
                                    <span class="py-char" :style="getCharStyle(word, item)">{{
                                      convertText(word.text)
                                    }}</span>
                                  </span>
                                </span>
                                <template v-else-if="word.type === 'input'">
                                  <span v-if="data.property.pinyin_position === 'top'" class="pinyin">&nbsp;</span>
                                  <span
                                    v-show="computedAnswerText(word, i, j).length > 0"
                                    :key="`answer-${j}`"
                                    class="right-answer"
                                  >
                                    {{ convertText(computedAnswerText(word, i, j)) }}
                                  </span>
                                  <span v-if="data.property.pinyin_position === 'bottom'" class="pinyin">&nbsp;</span>
                                </template>
                              </span>
                            </span>
                            <!-- 图片块 -->
                            <div
                              v-else-if="item.type === 'image'"
                              :key="'image-' + index"
                              :style="item.containerStyle"
                              class="image-container"
                            >
                              <img
                                :src="item.src"
                                :alt="item.alt"
                                :width="item.width"
                                :height="item.height"
                                :style="item.imageStyle"
                                class="inline-image"
                              />
                            </div>
                            <!-- 视频块 -->
                            <div
                              v-else-if="item.type === 'video'"
                              :key="'video-' + index"
                              :style="item.containerStyle"
                              class="video-container"
                            >
                              <video
                                :poster="item.poster"
                                :width="item.width"
                                :height="item.height"
                                :style="item.mediaStyle"
                                controls
                                class="inline-video"
                              >
                                <source :src="item.src" :type="item.videoType" />
                                您的浏览器不支持视频播放
                              </video>
                            </div>

                            <!-- 音频块 -->
                            <div
                              v-else-if="item.type === 'audio'"
                              :key="'audio-' + index"
                              :style="item.containerStyle"
                              class="audio-container"
                            >
                              <audio :src="item.src" :style="item.mediaStyle" controls class="inline-audio">
                                您的浏览器不支持音频播放
                              </audio>
                            </div>
                            <!-- 换行符 -->
                            <br v-else-if="item.type === 'newline'" :key="'newline-' + index" />
                          </div>
                        </template>
                      </template>
                      <template v-else>
                        <div v-for="(item, index) in col.model_essay" :key="index" :style="[tdStyle]">
                          <span
                            v-if="item.type === 'text'"
                            :key="index"
                            :style="{
                              fontSize:
                                data.unified_attrib && data.unified_attrib.font_size
                                  ? data.unified_attrib.font_size
                                  : '',
                              fontFamily:
                                data.unified_attrib && data.unified_attrib.font ? data.unified_attrib.font : '',
                            }"
                            v-html="convertText(sanitizeHTML(item.value))"
                          ></span>
                          <template v-if="item.type === 'input'">
                            <!-- <template v-if="data.property.fill_type === fillTypeList[0].value">
                            <el-input
                              :key="index"
                              v-model="item.value"
                              :disabled="disabled"
                              :class="[...computedAnswerClass(item, i, j)]"
                              :style="[{ width: Math.max(40, 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)"
                                >
                                  {{ convertText(content) }}
                                </span>
                              </div>

                              <el-input
                                slot="reference"
                                v-model="item.value"
                                :readonly="true"
                                :class="[...computedAnswerClass(item, i, j)]"
                                :style="[{ width: Math.max(40, 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' : ''"
                              :attrib="data.unified_attrib"
                              @handleWav="handleMiniWav($event, item)"
                            />
                          </template> -->

                            <span
                              v-show="computedAnswerText(item, i, j).length > 0"
                              :key="`answer-${j}`"
                              class="right-answer"
                            >
                              {{ convertText(computedAnswerText(item, i, j)) }}
                            </span>
                          </template>
                        </div>
                      </template>
                    </div>
                    <i
                      v-if="col.cell.isCross"
                      :class="[
                        { 'el-icon-check': data.answer_lists[i][j].crossAnswer === statusList[1] },
                        { 'el-icon-close': data.answer_lists[i][j].crossAnswer === statusList[2] },
                      ]"
                      style="display: block; width: 18px; height: 18px; border: 1px solid #30a47d"
                    ></i>
                  </div>
                  <span v-if="showLang" class="multilingual" :style="[tdStyle, computedRichStyle(col.content)]">
                    {{
                      multilingualTextList[getLang()] &&
                      multilingualTextList[getLang()][i] &&
                      multilingualTextList[getLang()][i][j]
                        ? multilingualTextList[getLang()][i][j]
                        : ''
                    }}
                  </span>
                </td>
              </template>
            </tr>
          </table>
        </div>
      </AnswerAnalysis>
    </div>
    <WriteDialog :visible.sync="writeVisible" @confirm="handleWriteConfirm" />
  </div>
</template>

<script>
import { getTableData, fillTypeList } from '@/views/book/courseware/data/table';

import PreviewMixin from '../common/PreviewMixin';
import WriteDialog from '../fill/components/WriteDialog.vue';
import SoundRecordBox from '@/views/book/courseware/preview/components/record_input/SoundRecord.vue';

export default {
  name: 'TablePreview',
  components: { SoundRecordBox, WriteDialog },
  mixins: [PreviewMixin],
  props: {
    isMobile: {
      type: Boolean,
      default: false,
    },
  },

  data() {
    return {
      data: getTableData(),
      table_width: 0,
      multilingualTextList: {}, // 多语言对应的切割后的翻译
      fillTypeList,
      selectedWordList: [], // 用于存储选中的词汇
      writeVisible: false,
      writeMark: '',
      isHasInput: false,
      statusList: ['normal', 'tick', 'cross'],
    };
  },
  computed: {
    tdStyle() {
      let obj = {};
      // if (this.data.mode === 'short') {
      let styles = this.data.styles;
      obj = {
        fontFamily: styles.fontFamily,
        fontSize: styles.fontSize,
        color: styles.fontColor,
        textDecoration: styles.isUnderline ? 'underline' : styles.isStrikethrough ? 'line-through' : '',
        fontWeight: styles.isBold ? 'bold' : '',
        fontStyle: styles.isItalic ? 'italic' : '',
        justifyContent: styles.textAlign === 'MIDDLE' ? 'center' : styles.textAlign === 'RIGHT' ? 'end' : 'left',
        textAlign: styles.textAlign === 'MIDDLE' ? 'center' : styles.textAlign === 'RIGHT' ? 'end' : 'left',
      };
      // } else {
      //   obj = {
      //     width: '100%',
      //   };
      // }
      return obj;
    },
  },
  watch: {
    'data.col_width': {
      handler(val) {
        this.handleData();
      },
    },
    'data.property': {
      handler(val) {
        this.computedTableCellShow();
      },
    },
    isJudgingRightWrong(val) {
      if (!val) return;
      this.data.answer_lists = this.answer.answer_list;
      // this.answer.answer_list.forEach(({ mark, value }) => {
      //   this.modelEssay.forEach((item) => {
      //     item.forEach((li) => {
      //       if (li.mark === mark) {
      //         li.content = value;
      //       }
      //     });
      //   });
      // });
    },
  },
  created() {
    this.handleData();
    this.computedTableCellShow();
  },
  methods: {
    // 预处理 richTextList，合并分散的视频标签
    normalizedRichTextList(col) {
      if (!col.rich_text_list || col.rich_text_list.length === 0) return [];

      const result = [];
      let i = 0;
      while (i < col.rich_text_list.length) {
        const item = col.rich_text_list[i];

        // 检查是否是视频开始标签（且不包含结束标签）
        if (
          item.text &&
          typeof item.text === 'string' &&
          item.text.includes('<video') &&
          !item.text.includes('</video>')
        ) {
          let combinedText = item.text;
          let j = i + 1;

          // 向后查找 source 和结束标签，直到遇到 </video> 或超出范围
          while (j < col.rich_text_list.length) {
            const nextItem = col.rich_text_list[j];
            if (nextItem.text) {
              combinedText += `${nextItem.text}`;
            }

            // 如果找到了结束标签，合并完成，跳出内部循环
            if (nextItem.text && nextItem.text.includes('</video>')) {
              j++; // 跳过结束标签
              break;
            }
            j++;
          }

          // 将合并后的内容作为一个新项加入结果
          result.push({
            ...item,
            text: combinedText,
            is_merged_video: true, // 标记一下，可选
          });

          // 更新主循环索引，跳过已合并的项
          i = j;
        } else {
          // 其他项直接加入
          result.push(item);
          i++;
        }
      }

      return result;
    },
    // 解析 richTextList 为可渲染的块
    parsedBlocks(col) {
      const listToParse = this.normalizedRichTextList(col);

      if (!listToParse || listToParse.length === 0) return [];
      // if (!col.rich_text_list || col.rich_text_list.length === 0) return [];
      const blocks = [];
      let textBlockIndex = 0;
      let oldIndex = -1;
      let paragraphIndex = 0;
      const tagStack = [];

      for (const item of listToParse) {
        oldIndex += 1;

        if (item.text && typeof item.text === 'string' && item.text.includes('<img')) {
          blocks.push(this.parseImageBlock(item, tagStack));
        } else if (item.text && typeof item.text === 'string' && item.text.includes('<video')) {
          // item.text 是完整的 video 标签串
          blocks.push(this.parseVideoBlock(item, tagStack));
        } else if (item.text && typeof item.text === 'string' && item.text.includes('<audio')) {
          blocks.push(this.parseAudioBlock(item, tagStack));
        } else if (item.is_style === 'true' || item.is_style === true) {
          if (item.text.includes('<br')) {
            blocks.push({ type: 'newline' });
            paragraphIndex += 1;
          } else {
            this.handleStyleTag(item, tagStack);
          }
        } else if (item.text === '\n') {
          blocks.push({ type: 'newline' });
          paragraphIndex += 1;
        } else if (item.word_list && item.word_list.length > 0) {
          const hasEmphasisDot = this.checkHasEmphasisDot(tagStack);
          blocks.push(this.createTextBlock(item, tagStack, textBlockIndex, oldIndex, paragraphIndex, hasEmphasisDot));
          textBlockIndex += 1;
        }
      }
      return blocks;
    },
    // 解析图片块
    parseImageBlock(item, tagStack) {
      const imgMatch = item.text.match(/<img\s+([^>]*)\/?\s*>/i);
      if (!imgMatch) return null;

      const attrs = imgMatch[1];
      const srcMatch = attrs.match(/src=["']([^"']*)["']/i);
      const altMatch = attrs.match(/alt=["']([^"']*)["']/i);
      const widthMatch = attrs.match(/width=["']?(\d+)["']?/i);
      const heightMatch = attrs.match(/height=["']?(\d+)["']?/i);
      const styleMatch = attrs.match(/style=["']([^"']*)["']/i);

      const containerStyleObj = {};
      tagStack.forEach((tagItem) => {
        if (tagItem.style) {
          this.mergeStyleString(containerStyleObj, tagItem.style);
        }
      });

      const imageStyleObj = {};
      if (styleMatch) {
        this.mergeStyleString(imageStyleObj, styleMatch[1]);
      }

      return {
        type: 'image',
        src: srcMatch ? srcMatch[1] : '',
        alt: altMatch ? altMatch[1] : '',
        width: widthMatch ? widthMatch[1] : null,
        height: heightMatch ? heightMatch[1] : null,
        containerStyle: containerStyleObj,
        imageStyle: imageStyleObj,
      };
    },
    // 处理样式标签
    handleStyleTag(item, tagStack) {
      const tagText = item.text || '';
      const closeTagMatch = tagText.match(/^<\/(\w+)>$/);

      if (closeTagMatch) {
        const tagName = closeTagMatch[1];
        this.removeTagFromStack(tagStack, tagName);
      } else {
        const openTagMatch = tagText.match(/^<(\w+)([^>]*)>$/);
        if (openTagMatch) {
          const tagName = openTagMatch[1];
          const attrs = openTagMatch[2];
          const { style, className } = this.extractTagInfo(attrs, tagName);
          tagStack.push({ tag: tagName, style, className });
        }
      }
    },
    // 检查标签栈中是否有着重点样式
    checkHasEmphasisDot(tagStack) {
      return tagStack.some((tagItem) => {
        if (!tagItem.className) return false;
        return tagItem.className.includes('rich-text-emphasis-dot');
      });
    },
    // 创建文本块
    createTextBlock(item, tagStack, textBlockIndex, oldIndex, paragraphIndex, hasEmphasisDot) {
      const combinedStyle = tagStack
        .filter((tagItem) => tagItem.style)
        .map((tagItem) => tagItem.style)
        .join(';');

      const styleObj = combinedStyle ? this.parseStyleToObject(combinedStyle) : null;

      return {
        type: 'text',
        word_list: item.word_list,
        index: textBlockIndex,
        oldIndex,
        paragraphIndex,
        styleObj,
        hasEmphasisDot,
      };
    },
    // 拼音固定为拼音字体，跟随汉字的字号、颜色、粗细的样式
    getPinyinStyle(item) {
      const styles = {};

      // 固定使用 League 字体
      styles['font-family'] = 'League';

      // 只继承字号和颜色
      if (item.activeTextStyle) {
        if (item.activeTextStyle.fontSize) {
          styles['font-size'] = item.activeTextStyle.fontSize;
        }
        if (item.activeTextStyle.color) {
          styles['color'] = item.activeTextStyle.color;
        }
      }

      // 如果设置了全局字号，优先使用全局字号
      if (this.isAllSetting && this.fontSize) {
        styles['font-size'] = this.fontSize;
        this.isAllSetting = false;
      }

      // 明确重置不应该继承的样式
      styles['text-decoration'] = 'none';
      styles['font-style'] = 'normal';
      styles['letter-spacing'] = '0';

      return styles;
    },
    // 获取单个字符的样式（包括着重点）
    getCharStyle(word, block, charIndex) {
      const baseStyle = { ...word.activeTextStyle };
      baseStyle['font-size'] = baseStyle.fontSize;
      baseStyle['font-family'] = baseStyle.fontFamily;

      if (this.isAllSetting) {
        baseStyle['font-size'] = this.fontSize;
        baseStyle['font-family'] = this.fontFamily;
        this.isAllSetting = false;
      }

      // 如果该文字块有着重点标记，应用到字符上
      if (block.hasEmphasisDot) {
        const letterSpacing = block.styleObj?.letterSpacing || '0';
        const letterSpacingValue = parseFloat(letterSpacing) || 0;

        baseStyle['border-bottom'] = 'none';
        baseStyle['background-image'] = 'radial-gradient(circle at center, currentColor 0.15em, transparent 0.16em)';
        baseStyle['background-repeat'] = 'repeat-x';
        baseStyle['background-position'] = `${letterSpacingValue * -0.5}em 100%`;
        baseStyle['background-size'] = `${1 + letterSpacingValue}em 0.3em`;
        baseStyle['padding-bottom'] = '0.3em';
        baseStyle['display'] = 'inline';
      }

      return baseStyle;
    },
    // 如果汉字有字间距，拼音与汉字左对齐，如果没有则居中对齐
    getWordAlignItems(word, block) {
      const letterSpacing = block.styleObj?.letterSpacing;
      if (letterSpacing && letterSpacing !== '0' && letterSpacing !== '0px') {
        return 'flex-start';
      }
      return 'center';
    },
    // 提取标签信息（样式和类名）
    extractTagInfo(attrs, tagName) {
      const styleMatch = attrs.match(/style=["']([^"']*)["']/);
      let style = styleMatch ? styleMatch[1] : null;

      const classMatch = attrs.match(/class=["']([^"']*)["']/);
      const className = classMatch ? classMatch[1] : '';

      if (!style) {
        style = this.getDefaultTagStyle(tagName);
      }

      return { style, className };
    },
    // 获取标签默认样式
    getDefaultTagStyle(tagName) {
      const tagStyleMap = {
        strong: 'font-weight: bold',
        b: 'font-weight: bold',
        em: 'font-style: italic',
        i: 'font-style: italic',
        u: 'text-decoration: underline',
        s: 'text-decoration: line-through',
        del: 'text-decoration: line-through',
        sub: 'vertical-align: sub',
        sup: 'vertical-align: super',
      };
      return tagStyleMap[tagName] || null;
    },
    // 解析样式字符串为对象
    parseStyleToObject(styleStr) {
      const styleObj = {};
      if (!styleStr) return styleObj;

      this.mergeStyleString(styleObj, styleStr);
      return styleObj;
    },
    // 解析视频块
    parseVideoBlock(item, tagStack) {
      const videoMatch = item.text.match(/<video\s+([^>]*)>/i);
      if (!videoMatch) return null;

      const attrs = videoMatch[1];
      const posterMatch = attrs.match(/poster=["']([^"']*)["']/i);
      const widthMatch = attrs.match(/width=["']?(\d+)["']?/i);
      const heightMatch = attrs.match(/height=["']?(\d+)["']?/i);
      const styleMatch = attrs.match(/style=["']([^"']*)["']/i);

      // 直接从完整的文本中匹配 source
      const sourceMatch = item.text.match(/<source\s+([^>]*)\/?\s*>/i);
      let src = '';
      let videoType = '';

      if (sourceMatch) {
        const sourceAttrs = sourceMatch[1];
        const srcMatch = sourceAttrs.match(/src\s*=\s*["']?([^"'\s>]+)["']?/i);
        const typeMatch = sourceAttrs.match(/type\s*=\s*["']?([^"'\s>]+)["']?/i);

        src = srcMatch ? srcMatch[1] : '';
        videoType = typeMatch ? typeMatch[1] : '';
      }

      const containerStyleObj = {};
      tagStack.forEach((tagItem) => {
        if (tagItem.style) {
          this.mergeStyleString(containerStyleObj, tagItem.style);
        }
      });

      const mediaStyleObj = {};
      if (styleMatch) {
        this.mergeStyleString(mediaStyleObj, styleMatch[1]);
      }

      return {
        type: 'video',
        poster: posterMatch ? posterMatch[1] : '',
        width: widthMatch ? widthMatch[1] : null,
        height: heightMatch ? heightMatch[1] : null,
        src,
        videoType,
        containerStyle: containerStyleObj,
        mediaStyle: mediaStyleObj,
      };
    },

    // 解析音频块
    parseAudioBlock(item, tagStack) {
      const audioMatch = item.text.match(/<audio\s+([^>]*)>/i);
      if (!audioMatch) return null;

      const attrs = audioMatch[1];
      const srcMatch = attrs.match(/src=["']([^"']*)["']/i);
      const styleMatch = attrs.match(/style=["']([^"']*)["']/i);

      const containerStyleObj = {};
      tagStack.forEach((tagItem) => {
        if (tagItem.style) {
          this.mergeStyleString(containerStyleObj, tagItem.style);
        }
      });

      const mediaStyleObj = {};
      if (styleMatch) {
        this.mergeStyleString(mediaStyleObj, styleMatch[1]);
      }

      return {
        type: 'audio',
        src: srcMatch ? srcMatch[1] : '',
        containerStyle: containerStyleObj,
        mediaStyle: mediaStyleObj,
      };
    },
    // 合并样式字符串到对象
    mergeStyleString(styleObj, styleStr) {
      styleStr.split(';').forEach((rule) => {
        if (rule.trim()) {
          const [prop, value] = rule.split(':').map((s) => s.trim());
          if (prop && value) {
            const camelProp = prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
            styleObj[camelProp] = value;
          }
        }
      });
    },
    removeTagFromStack(tagStack, tagName) {
      for (let i = tagStack.length - 1; i >= 0; i--) {
        if (tagStack[i].tag === tagName) {
          tagStack.splice(i, 1);
          break;
        }
      }
    },
    toggle(status) {
      const index = this.statusList.findIndex((item) => status.crossAnswer === item);
      status.crossAnswer = index === this.statusList.length - 1 ? this.statusList[0] : this.statusList[index + 1];
    },
    handleData() {
      this.table_width = 0;
      this.isHasInput = false;
      this.data.col_width.forEach((item) => {
        this.table_width += Number(item.value);
      });
      this.data.multilingual.forEach((item) => {
        let trans_arr = item.translation.split('\n');
        let chunkSize = this.data.property.column_count;
        let chunkedArr = trans_arr.reduce((acc, curr, index) => {
          // 当索引是chunkSize的倍数时，开始一个新的子数组
          if (index % chunkSize === 0) {
            acc.push([curr]); // 开始新的子数组并添加当前元素
          } else {
            acc[acc.length - 1].push(curr); // 将当前元素添加到最后一个子数组中
          }
          return acc;
        }, []);
        this.$set(this.multilingualTextList, item.type, chunkedArr);
      });
      if (!this.isJudgingRightWrong) {
        this.answer.answer_list = this.data.answer_lists;
      }
      this.data.option_list.forEach((item, index) => {
        item.forEach((items, indexs) => {
          items.model_essay.forEach((li) => {
            if (li.type === 'input') {
              this.isHasInput = true;
            }
          });
          if (items.rich_text_list) {
            this.data.option_list[index][indexs].rich_text_list = this.parsedBlocks(items);
          }
        });
      });
    },
    // 计算单元格是否显示
    computedTableCellShow() {
      this.data.option_list.forEach((item, i, arr) => {
        item.forEach(({ cell, is_show_cell }, j, arr2) => {
          let col = cell.colspan === undefined ? 1 : Number(cell.colspan);
          let row = cell.rowspan === undefined ? 1 : Number(cell.rowspan);

          if (col > 1 && row === 1) {
            for (let k = 1; k < col; k++) {
              this.$set(arr[i][j + k], 'is_show_cell', false);
            }
          }
          if (row > 1 && col === 1) {
            for (let k = 1; k < row; k++) {
              this.$set(arr[i + k][j], 'is_show_cell', false);
            }
          }
          if (row > 1 && col > 1) {
            for (let k = 1; k < row; k++) {
              this.$set(arr[i + k][j], 'is_show_cell', false);
              for (let l = 1; l < col; l++) {
                this.$set(arr[i + k][j + l], 'is_show_cell', false);
                this.$set(arr[i][j + l], 'is_show_cell', false);
              }
            }
          }
          if (is_show_cell === undefined) {
            arr2[j].is_show_cell = true;
          }
        });
      });
    },
    computedAnswerText(item, i, j) {
      if (!this.isShowRightAnswer) return '';
      let answerOption =
        this.data.answer_lists[i] && this.data.answer_lists[i][j] ? this.data.answer_lists[i][j].answer : '';
      let answerOptionList = answerOption.split('\n');
      if (!item) return '';
      let answerValue = answerOptionList[item.inputIndex] ? answerOptionList[item.inputIndex].split('/') : '';
      if (!answerValue) return '';
      return `${answerValue.join('/')}`;
    },
    /**
     * 计算答题对错选项字体颜色
     * @param {string} mark 选项标识
     */
    computedAnswerClass(item, i, j) {
      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
        return '';
      }
      let answerOption =
        this.data.answer_lists[i] && this.data.answer_lists[i][j] ? this.data.answer_lists[i][j].answer : '';
      let answerOptionList = answerOption.split('\n');
      if (!item) return '';
      let selectValue = item.value ? item.value.trim() : '';
      let answerValue = answerOptionList[item.inputIndex] ? answerOptionList[item.inputIndex].split('/') : '';
      let classList = [];
      let isRight = answerValue && answerValue.includes(selectValue);
      if (this.isJudgingRightWrong && answerValue) {
        isRight ? classList.push('right') : classList.push('wrong');
      }

      if (this.isShowRightAnswer && !isRight) {
        classList.push('show-right-answer');
      }
      return classList;
    },
    computedAnswerCrossClass(item, i, j) {
      if (!this.isJudgingRightWrong && !this.isShowRightAnswer) {
        return '';
      }
      let answerOption =
        this.data.answer_lists[i] && this.data.answer_lists[i][j] ? this.data.answer_lists[i][j].crossAnswer : '';
      if (!item) return '';
      let selectValue = item.crossAnswer;
      let classList = [];
      let isRight = answerOption === selectValue;
      if (this.isJudgingRightWrong && answerOption) {
        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 || this.disabled) 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;
    },
    computedRichStyle(content) {
      // if (this.data.mode === 'short') return {};
      if (!content) return {};
      // 提取首个标签的 style 样式属性
      let styleMatch = content.match(/<\w+\s+[^>]*style=["']([^"']*)["'][^>]*>/i);
      if (styleMatch && styleMatch[1]) {
        let styleString = styleMatch[1];
        let styleArray = styleString.split(';').filter((s) => s.trim() !== '');
        let styleObject = {};
        styleArray.forEach((style) => {
          let [key, value] = style.split(':');
          if (key && value) {
            styleObject[key.trim()] = value.trim();
          }
        });
        if (styleObject.hasOwnProperty('text-align') && styleObject['text-align'] === 'center') {
          this.$set(styleObject, 'justify-content', 'center');
        }
        return styleObject;
      }
      return {};
    },
    // 重做
    retry() {
      this.data.option_list.forEach((item) => {
        item.forEach((items) => {
          items.model_essay.forEach((li) => {
            if (li.type === 'input') {
              li.value = '';
              li.write_base64 = '';
            }
          });
        });
      });
      if (this.$refs.record) {
        if (this.$refs.record.length > 0) {
          this.$refs.record.forEach((item) => {
            item.handleReset();
          });
        } else {
          this.$refs.record.handleReset();
        }
      }
      this.isJudgingRightWrong = false;
      this.isShowRightAnswer = false;
    },
    /**
     * 获取无文本内容的数据结构，用于保存为个人模板时的样式模板
     */
    getNoTextContentData() {
      let noTextContentData = JSON.parse(JSON.stringify(this.data));
      const resetFieldMap = {
        record_list: [],
        vocabulary: '', // 用于选词的词汇
        word_list: [], // 选词列表
        has_identify: 'false', // 是否已识别
        paragraph_list: [],
        paragraph_list_parameter: {
          text: '',
          is_first_sentence_first_hz_pinyin_first_char_upper_case: 'true',
          pinyin_proofread_word_list: [],
        },
        analysis_list: [],
        answer_list: [],
      };

      Object.assign(noTextContentData, resetFieldMap);

      noTextContentData.answer_lists.forEach((item) => {
        item.answer = '';
        item.answer_list = [];
      });
      noTextContentData.option_list.forEach((item) => {
        item.content = '';
        item.model_essay = [];
      });

      if (noTextContentData.answer) {
        noTextContentData.answer.answer_list = [];
        noTextContentData.answer.reference_answer = '';
      }

      return noTextContentData;
    },
  },
};
</script>

<style lang="scss" scoped>
@use '@/styles/mixin.scss' as *;

$select-color: #1890ff;
$border-color: #e6e6e6;

.table-preview {
  @include preview-base;

  .main {
    color: #262626;

    .table-box {
      margin: 0 auto;
      overflow: auto;
    }

    table {
      // border-spacing: 3px;
      border-collapse: separate;
    }

    .cell-wrap {
      display: flex;
      flex-flow: wrap;
      grid-area: fill;

      // align-items: end;
      align-items: center; // 为了勾选框居中对齐
      &-content {
        display: flex;
        flex: 1;
        flex-flow: wrap;
        grid-area: fill;
        align-items: end;
      }

      p {
        flex-grow: 1; // 为了常规模式时设置居中显示撑满整个单元格
        max-width: 100%;
        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;
        width: 120px;
        margin: 0 2px;
        font-size: 16px;

        &.pinyin :deep input.el-input__inner {
          font-family: 'PINYIN-B', sans-serif;
        }

        &.chinese :deep input.el-input__inner {
          font-family: 'arial', sans-serif;
        }

        &.english :deep input.el-input__inner {
          font-family: 'arial', sans-serif;
        }

        &.right {
          :deep input.el-input__inner {
            color: $right-color;
          }
        }

        &.wrong {
          :deep input.el-input__inner {
            color: $error-color;
          }
        }

        :deep input.el-input__inner {
          padding: 0;

          // font-size: 16pt;
          color: $font-color;
          text-align: center;
          background-color: transparent;
          border-width: 0;
          border-bottom: 1px solid $font-color;
          border-radius: 0;
        }
      }

      .right {
        border-color: $right-color !important;
      }

      .wrong {
        border-color: $error-color !important;
      }

      &-normal {
        p {
          width: 100%; // 为了解决换行问题
        }
      }
    }

    .right-answer {
      position: relative;
      left: 0;
      display: inline-block;
      min-height: 24px;
      line-height: 24px;
      vertical-align: bottom;
      border-bottom: 1px solid $font-color;
    }

    .multilingual {
      display: block;
      word-break: break-word;
    }

    .pinyin-text {
      display: flex;
      flex-direction: column;
      padding: 0 1px;
      font-size: 16px;

      span {
        text-align: center;
      }

      .pinyin {
        height: 18px;
        font-family: 'League';
        font-size: 12px;
      }

      &-left {
        span {
          // text-align: left;
        }
      }
    }

    .cell-wrap-content {
      p {
        display: inline-flex;
        flex-wrap: wrap;
        margin: 0.5em 0;
      }

      span {
        display: inline-flex;
      }

      .pinyin-sentence {
        display: inline;
        white-space: normal;
      }

      .image-container {
        display: block;

        .inline-image {
          display: inline-block;
          max-width: 100%;
          height: auto;
        }
      }

      .video-container {
        display: inline-block;
        margin: 26px 5px 26px 0;

        .inline-video {
          display: inline-block;
          max-width: 100%;
          height: auto;
        }
      }

      .audio-container {
        display: inline-block;

        .inline-audio {
          display: inline-block;
          width: 100%;
          max-width: 500px;
        }
      }

      .pinyin-text-audio {
        width: 100%;
      }
    }

    :deep .el-input--small .el-input__inner {
      height: 100%;
      line-height: 1;
    }

    :deep audio,
    :deep video {
      max-width: 100%;
    }
  }
}

.word-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;

  .word-item {
    cursor: pointer;
  }
}
</style>
