<script setup lang="ts">
import SingleChoice from '@c/question/answer/SingleChoice.vue'
import Judgment from '@c/question/answer/Judgment.vue'
import JudgmentCloze from '@c/question/answer/JudgmentCloze.vue'
import MultipleChoice from '@c/question/answer/MultipleChoice.vue'
import ClozeTest from '@c/question/answer/ClozeTest.vue'
// import Other from '@c/question/answer/Other.vue'
import HandDrawn from '@c/question/answer/HandDrawn.vue'
import CompositeStem from '@c/question/answer/CompositeStem.vue'
import Input from '@c/question/answer/Input.vue'
import { useAudio, TypeSet } from '@/hooks'
import EchartsBar from '@/page/system/homework/reports/components/EchartsBar.vue'
import { useRoute } from 'vue-router'
import VideoFullBox from '@/page/subject/components/VideoFullBox/index.vue'
import { resource_type_analogy } from '@/page/subject/doWork'
import Feedback from '@/page/subject/doWork/components/Feedback.vue'
import AiReplyDia from '@/page/subject/doWork/components/AiReplyDia.vue'
import router from '@/router'
import homeWorkApi from '@/api/system/homeWork'
import clozeTest from '@/components/ClozeTest/index.vue'
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue'

import { dialog } from '@/components/mj/mj-dialog'
import hud from '@/utils/hud'

const props = defineProps<{
  data: any
  idx: number
  total: number
  // 0或者1
  reportFlag: number
  uploadFile: any
  beforeUpload: any
  isDeadline: boolean
  isHomework?: boolean
  resourceType: any
  explainMode?: boolean
}>()

const emit = defineEmits(['submit', 'handleTime'])

const OSS_URL = import.meta.env.VITE_OSS_URL

defineOptions({
  name: 'Question',
})

const route = useRoute()

// stem 中含 .qml-sq 子题且子题带可选选项(.qml-op)时视为复合题
// stemType=1 的混合型大题不走复合题逻辑，子题仅展示，答题统一使用手写画板
const isCompositeStem = computed(() => {
  if (props.data?.stemType === 3) return true
  if (props.data?.stemType === 1) return false
  if (!props.data?.stem) return false
  return props.data.stem.includes('qml-sq') && props.data.stem.includes('qml-op')
})

function getAnswerCountFromAnswerHtml(answerHtml: unknown) {
  if (!answerHtml) return 0
  if (Array.isArray(answerHtml)) return answerHtml.filter(Boolean).length

  if (typeof answerHtml === 'string') {
    const raw = answerHtml.trim()
    if (!raw) return 0

    try {
      const parsed = JSON.parse(raw)
      if (Array.isArray(parsed)) return parsed.filter(Boolean).length
    } catch {
      /* ignore */
    }

    const plainText = raw
      .replace(/<[^>]*>/g, '')
      .replace(/&nbsp;/gi, ' ')
      .trim()
    if (!plainText) return 0
    return plainText.split(/[，,\s]+/).filter(Boolean).length
  }

  return 0
}

const isSingleChoiceByAnswerHtml = computed(() => {
  return props.data?.stemType === 2 && getAnswerCountFromAnswerHtml(props.data?.answerHtml) === 1
})

// 从 answerHtml 中提取选择题答案字母 (如 "A" 或 "A,B,C")
function extractChoiceLettersFromAnswerHtml(answerHtml: unknown): string {
  if (!answerHtml) return ''
  if (Array.isArray(answerHtml)) {
    return answerHtml
      .filter(Boolean)
      .map((v: any) => String(v).trim().toUpperCase())
      .filter(v => /^[A-Z]$/.test(v))
      .join(',')
  }
  if (typeof answerHtml === 'string') {
    const raw = answerHtml.trim()
    if (!raw) return ''

    try {
      const parsed = JSON.parse(raw)
      if (Array.isArray(parsed)) {
        return parsed
          .filter(Boolean)
          .map((v: any) => String(v).trim().toUpperCase())
          .filter(v => /^[A-Z]$/.test(v))
          .join(',')
      }
    } catch {
      /* ignore */
    }

    const plainText = raw
      .replace(/<[^>]*>/g, '')
      .replace(/&nbsp;/gi, ' ')
      .toUpperCase()
    const letters = plainText.match(/[A-Z]/g)
    if (letters && letters.length) {
      return Array.from(new Set(letters)).join(',')
    }
  }
  return ''
}

// 选择题（单选/多选）的正确答案，优先使用 answerHtml
const choiceAnswer = computed(() => {
  const stemType = props.data?.stemType
  if (stemType !== 2 && stemType !== 3) return ''
  return (
    extractChoiceLettersFromAnswerHtml(props.data?.answerHtml) ||
    props.data?.answerSqs ||
    props.data?.answer ||
    ''
  )
})

const component = computed(() => {
  const stemType = props.data?.stemType

  if (isCompositeStem.value) return CompositeStem
  if (stemType === 3) return MultipleChoice
  if (stemType === 2) return isSingleChoiceByAnswerHtml.value ? SingleChoice : MultipleChoice
  return HandDrawn
})

// 从 stem HTML 中提取主题干（去掉 qml-sq 子题部分）
const stemIntro = computed(() => {
  if (!isCompositeStem.value || !props.data?.stem) return ''
  try {
    const parser = new DOMParser()
    const doc = parser.parseFromString(props.data.stem, 'text/html')
    const root = doc.body.querySelector('.qml-stem') || doc.body
    const cloned = root.cloneNode(true) as HTMLElement
    cloned.querySelectorAll('.qml-sq').forEach(el => el.remove())
    return cloned.innerHTML.trim()
  } catch {
    return props.data.stem
  }
})

// stemType === 3 时题目字段取 stemSqs
const stemText = computed(() => {
  if (props.data?.stemType === 3) {
    return (
      props.data?.stemSqs ||
      stemIntro.value ||
      props.data?.stemHtml ||
      props.data?.title ||
      props.data?.stem
    )
  }
  if (isCompositeStem.value) return stemIntro.value
  return props.data?.stemHtml || props.data?.title || props.data?.stem
})

const parsedOptionHtml = computed(() => {
  const raw = props.data?.optionHtml
  if (!raw) return undefined
  try {
    const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw
    if (Array.isArray(parsed)) {
      return [parsed.map((item: any) => item.html || '')]
    }
  } catch {
    /* ignore */
  }
  return undefined
})

// 图片预览
const imgDia = reactive({
  show: false,
  url: '',
})
function handleShow(url: string) {
  if (url) {
    imgDia.show = true
    imgDia.url = url
  }
}

const resultClass = computed(() => {
  return (data: any) => {
    if (!data)
      return {
        class: 'info',
        text: 0 + '分',
        // icon: 'emoji_info',
      }
    if (data.titleStatus === 2) {
      return {
        class: 'wait',
        text: '待批改',
        // icon: 'emoji_info',
      }
    } else if (!data.markFlag && !data.submitAnswer && !data.submitAnswerPic) {
      return {
        class: 'empty',
        text: '未作答',
        icon: 'emoji_empty',
      }
    } else if (data?.actualScore !== 0 && data?.actualScore !== data?.score) {
      return {
        class: 'info',
        text: '部分正确',
      }
    } else if (data.correctResult || data.markFlag) {
      return {
        class: 'success',
        text: '答对啦',
        icon: 'emoji_success',
      }
    }
    // else if (data.actualScore > 0) {
    //   return {
    //     class: 'info',
    //     text: data.actualScore + '分',
    //     // icon: 'emoji_info',
    //   }
    // }
    else {
      return {
        class: 'error',
        text: '答错了',
        icon: 'emoji_fail',
      }
    }
  }
})

// 给子题目添加序号
const filterTitle = computed(() => {
  return (title: string | undefined, cidx?: number) => {
    if (!title) return undefined
    // 填空题的下划线
    title = title.replace(/<u><\/u>/g, '<u class="fill-blank"></u>')
    let t = title.replace(/http:\/\//gi, 'https://')
    // .replace(/contenteditable/g, 'no-contenteditable');
    if (props.data?.sourceType === 1) {
      t = t.replace(/\\n/g, '<br>')
    }
    if (cidx !== undefined) {
      return `(${cidx + 1})` + t
    } else {
      return t
    }
  }
})

// ========== 阅读理解 / 完形填空检测（参照小程序逻辑） ==========
function toSimpleOptions(list: any[]) {
  return list.map((value: any, idx: number) => {
    let v = value ?? ''
    if (typeof v === 'object' && v !== null) {
      v = v.html || v.value || v.optionValue || v.content || ''
    }
    return {
      label: String.fromCharCode(65 + idx),
      value: typeof v === 'string' ? v : String(v),
    }
  })
}

function normalizeOptionsFromOptionList(optionList: any[]) {
  if (!Array.isArray(optionList) || !optionList.length) return undefined
  let list = optionList
  // 解包多余嵌套 [[...]] → [...]
  while (Array.isArray(list) && list.length === 1 && Array.isArray(list[0])) {
    list = list[0]
  }
  // 数组的数组 → 完形填空结构 [{ options: [{label, value}] }]
  if (
    list.every((i: any) => Array.isArray(i)) &&
    list.some((i: any) => Array.isArray(i) && i.length)
  ) {
    return (list as any[]).map((sub: any[]) => ({ options: toSimpleOptions(sub) }))
  }
  // 纯字符串数组 → 简单选项 [{label, value}]
  if (list.every((i: any) => typeof i === 'string')) {
    return toSimpleOptions(list as any[])
  }
  return list
}

// 解析原始 options 数据
const rawParsedOptions = computed(() => {
  const data = props.data

  // stemType=3 复合题: 从 stemSqs + optionSqs 解析子题数据
  if (data?.stemType === 3) {
    let stems: string[] = []
    if (data.stemSqs) {
      try {
        const parsed = typeof data.stemSqs === 'string' ? JSON.parse(data.stemSqs) : data.stemSqs
        if (Array.isArray(parsed)) stems = parsed
      } catch {
        /* ignore */
      }
    }

    let opts: any[][] = []
    if (data.optionSqs) {
      try {
        const parsed =
          typeof data.optionSqs === 'string' ? JSON.parse(data.optionSqs) : data.optionSqs
        if (Array.isArray(parsed)) opts = parsed
      } catch {
        /* ignore */
      }
    }

    const maxLen = Math.max(stems.length, opts.length)
    if (maxLen === 0) return []

    return Array.from({ length: maxLen }, (_, idx) => ({
      stem: stems[idx] || '',
      options: Array.isArray(opts[idx]) ? toSimpleOptions(opts[idx]) : [],
    }))
  }

  let raw: any =
    data?.optionsMu !== null && data?.optionsMu !== undefined
      ? data.optionsMu
      : data?.options !== null && data?.options !== undefined
        ? data.options
        : null
  if (typeof raw === 'string') {
    try {
      raw = JSON.parse(raw)
    } catch {
      raw = null
    }
  }
  if (Array.isArray(raw)) {
    return normalizeOptionsFromOptionList(raw) ?? raw
  }
  return []
})

// 是否为阅读理解（选项含 stem + options 子结构）
const isYueDu = computed(() => {
  if (props.data?.stemType === 2) return false
  const list = rawParsedOptions.value
  if (!list.length) return false
  return list.some((item: any) => item?.options && item?.stem)
})

// 是否为完形填空（选项含 options 子结构但无 stem）
const isWanXing = computed(() => {
  if (isYueDu.value) return false
  if (props.data?.stemType === 2) return false
  const list = rawParsedOptions.value
  if (!list.length) return false
  return list.some((item: any) => item?.options && !item?.stem)
})

// 阅读理解 / 完形填空：子题列表
const yueDuList = computed(() => {
  if (!isYueDu.value && !isWanXing.value) return []
  return rawParsedOptions.value.map((item: any, idx: number) => {
    const rawSubOpts = Array.isArray(item.options) ? item.options : []
    const subOpts = rawSubOpts.map((opt: any, oIdx: number) => {
      let v = typeof opt === 'string' ? opt : (opt?.value ?? opt?.optionValue ?? '')
      if (typeof v === 'object' && v !== null) {
        v = v.html || v.value || v.optionValue || v.content || ''
      }
      v = v !== null && v !== undefined ? String(v) : ''
      v = v.replace(/http:\/\//gi, 'https://')
      return {
        label:
          typeof opt === 'string'
            ? String.fromCharCode(65 + oIdx)
            : opt?.label || opt?.optionKey || String.fromCharCode(65 + oIdx),
        value: v,
      }
    })
    let stem = ''
    if (item.stem) {
      stem = String(item.stem).replace(/http:\/\//gi, 'https://')
    }
    // 判断选项是否适合水平排列
    let horizontal = false
    if (subOpts.length > 0) {
      const maxLen = Math.max(
        ...subOpts.map((o: any) => String(o.value || '').replace(/<[^>]*>/g, '').length),
      )
      horizontal = maxLen < 10
    }
    return { index: idx, stem, options: subOpts, horizontal }
  })
})

/**
 * @description: 音频
 */
// 音频是否正在播放
const isAudioPlay = ref(false)
// 音频播放器
let audioPlayer: anyObj = {}
// 播放音频
function playAudio() {
  if (isAudioPlay.value) {
    audioPlayer.pause()
  } else {
    audioPlayer.src = props.data?.voiceUrl
    audioPlayer.play()
  }
}

// 视频播放器
const videoDia = reactive<anyObj>({
  show: false,
  // videoList: [],
  knowledge: {},
})
function playVideo(item: anyObj) {
  if (item.videoList?.length) {
    videoDia.show = true
    videoDia.knowledge.id = item.id
    videoDia.knowledge.name = item.name
  }
}

// 填空题 同步答案
const quizList = ref<anyObj[]>([])
function inputChange(val: string, idx: number) {
  quizList.value[idx].innerText = val
}

const jobStuStatistics = ref<anyObj>([])

const rightRef = ref()
const echartsRef = ref()
const echartsData = reactive<{ xData: string[]; seriesVal: anyObj[] }>({
  xData: [],
  seriesVal: [],
})
watch(
  () => props.data?.id,
  async nv => {
    if (nv) {
      // 切换题目时初始化音频 初始化右边区域滑动条
      audioPlayer?.pause?.()
      rightRef.value && (rightRef.value.scrollTop = 0)
      await nextTick()
      TypeSet([document.querySelector('.question-item')])
      // 题目里所有图片添加点击放大查看事件
      document.querySelectorAll('.dowork .left-title img').forEach((i: anyObj) => {
        i?.addEventListener('click', () => {
          handleShow(i?.src)
        })
      })
      document.querySelectorAll('.dowork .choice-box img').forEach((i: anyObj) => {
        i?.addEventListener('click', (e: any) => {
          handleShow(i?.src)
          e?.stopPropagation?.()
        })
      })
      document.querySelectorAll('.dowork .answer-box-main img').forEach((i: anyObj) => {
        i?.addEventListener('click', () => {
          handleShow(i?.src)
        })
      })
      document.querySelectorAll('.dowork .analyze-title img').forEach((i: anyObj) => {
        i?.addEventListener('click', () => {
          handleShow(i?.src)
        })
      })

      // 不可以编辑填空框
      document.querySelectorAll('.dowork .left-title .quizPutTag').forEach((i: anyObj) => {
        i?.setAttribute('contenteditable', 'false')
      })

      // 作业里面的统计
      if (props.reportFlag && props.data?.jobId) {
        const { data: res } = await homeWorkApi.getJobStatistics({
          titleId: props.data?.id,
          jobId: props.data?.jobId,
          stuId: route.query.stuId || '',
        })

        jobStuStatistics.value = res.data?.map((i: anyObj) => i.scStuList) || []
        echartsData.xData = []
        echartsData.seriesVal = []
        res.data?.forEach((i: anyObj) => {
          echartsData.xData.push(i.intervalValue + '分')
          echartsData.seriesVal.push({
            value: i.num,
            itemStyle: {
              color: i.curFlag ? '#FE8200' : '#7FADFF',
            },
          })
        })
        nextTick(() => {
          echartsRef.value?.drawGraph()
        })
      }

      // 填空题 同步答案
      if (props.data?.fillBlankNum) {
        quizList.value = []
        document
          .querySelectorAll('.quizPutTag[contenteditable]')
          .forEach((i: anyObj, idx: number) => {
            i.setAttribute('contenteditable', false)
            i.innerText = props.data?.submitAnswer?.split(',')?.[idx] || ''
            quizList.value.push(i)
          })
      }
    }
  },
  { immediate: true },
)
const xlDia = reactive<{ show: boolean; data: anyObj[] }>({
  show: false,
  data: [],
})

function handleBarClick(params: anyObj) {
  const arr = jobStuStatistics.value[params.dataIndex]
  if (arr?.length) {
    xlDia.show = true
    xlDia.data = arr.map((i: anyObj) => ({
      id: i.id,
      name: i.stuName,
    }))
  }
}

// 错题反馈
const feedbackDia = reactive<anyObj>({
  show: false,
  data: {},
})
function handleFeedback() {
  const item = props.data
  feedbackDia.show = true
  feedbackDia.data = {
    titleId: item.id,
    subjectId: item.subjectId,
  }
}

let aiReplyVisible = ref(false)
// AI智答
async function handleAiReply() {
  aiReplyVisible.value = true
}

// AI智能批改
async function handleAiGrade() {
  hud.load({
    task: async () => {
      const { data: res } = await homeWorkApi.gradeQuestionTitleByAI(props.data?.itemId)
      if (res.data) {
        Object.assign(props.data, res.data)
      }
      // 接口调用成功后刷新页面
      location.reload()
    },
    option: 'AI智能批改',
    hideSuccess: true,
  })
}

// 提醒名字
const typeName = computed(() => {
  return (
    props.data?.typeName ||
    props.data?.titleChannelTypeName ||
    props.data?.channelTypeName ||
    '选择题'
  )
})

const isCollapsed = ref(false)
const showCollapseBtn = computed(() => {
  return route.path.startsWith('/subject/doWork') || props.explainMode
})

// 有 AI 答案或 AI 点评数据时在报告模式显示（不限制是否得满分）
const showAiAnswer = computed(() => {
  return (
    props.reportFlag &&
    !['单选题', '多选题', '选择题'].includes(typeName.value) &&
    (props.data?.aiAnswer || props.data?.aiAnalyze)
  )
})

const explanationText = computed(() => {
  return props.data?.explanation || props.data?.titleAnalyze || ''
})

// 举一反三
function handleAnalogy() {
  const item = props.data
  const routeObj = {
    path: '/subject/doWork',
    query: {
      resourceType: resource_type_analogy,
      subjectId: item.subjectId,
      titleId: item.id,
      num: 3,
    },
  }
  if (props.resourceType === resource_type_analogy) {
    router.replace(routeObj)
  } else {
    router.push(routeObj)
  }
}

;(() => {
  nextTick(() => {
    audioPlayer = useAudio({
      autoplay: false,
    })
    audioPlayer.on('play', () => {
      isAudioPlay.value = true
    })
    audioPlayer.on('pause', () => {
      isAudioPlay.value = false
    })
    audioPlayer.on('ended', () => {
      isAudioPlay.value = false
    })
  })
})()

onUnmounted(() => {
  imgDia.show = false
  imgDia.url = ''
  audioPlayer?.destroy?.()
  isAudioPlay.value = false
})

// watch(
//     () => feedbackDia.show,
//     nv => {
//         // 弹出错题反馈对话框时，停止计时
//         if (nv) {
//             clearInterval(timeout)
//         } else {
//             startTime()
//         }
//     }
// )
</script>
<template>
  <div class="question-item">
    <div class="top">
      <div v-if="props.data?.difficultyLevel" class="difficulty-start_box">
        <DifficultyStart disabled :modelValue="props.data?.difficultyLevel"></DifficultyStart>
      </div>
      <div class="title-type">
        {{ props.idx }}/{{ props.total }} {{ typeName }}
        <span v-if="props.data?.score">({{ props.data?.score }}分)</span>
      </div>
      <!-- 不是作业时，才显示 -->

      <div v-if="reportFlag && !isHomework && !explainMode" class="right-top">
        <!-- <mj-button type="primary" width="192" height="64" size="32" @click="handleAiReply">
          AI解析
        </mj-button> -->
        <mj-button
          v-if="props.data?.correctResult === null"
          type="primary"
          width="192"
          height="64"
          size="32"
          @click="handleAiGrade"
        >
          AI智能批改
        </mj-button>
        <mj-button
          v-if="String(resourceType) === '0'"
          type="warn"
          width="192"
          height="64"
          size="32"
          @click="handleAnalogy"
        >
          举一反三
        </mj-button>
        <mj-button
          type="danger"
          width="192"
          height="64"
          size="32"
          class="feedback"
          @click="handleFeedback"
        >
          错题反馈
        </mj-button>
      </div>
    </div>
    <!-- 折叠按钮 -->
    <div class="main-box" :class="{ collapsed: isCollapsed }">
      <mj-button
        v-if="showCollapseBtn"
        class="collapse-btn"
        type="primary"
        @click="isCollapsed = !isCollapsed"
      >
        <el-icon v-if="isCollapsed"><ArrowLeft /></el-icon>
        <el-icon v-else><ArrowRight /></el-icon>
      </mj-button>
      <div class="left hidden_scroll">
        <latex-text v-if="stemText" class="left-title" :text="filterTitle(stemText)"></latex-text>
        <!-- 子题目  如果是选择题或者多选题不显示-->
        <cloze-test
          v-if="
            data?.options?.length &&
            !isYueDu &&
            !isWanXing &&
            !['单选题', '多选题', '选择题'].includes(typeName)
          "
          class="left-children"
          :options="data?.options"
        />
        <!-- <div v-if="data?.title" class="left-title" v-html="filterTitle(data?.title)"></div> -->
        <div v-if="data?.voiceUrl" class="left-voice">
          <Horn :active="isAudioPlay" @click="playAudio"></Horn>
        </div>
        <div v-if="data?.children?.length && !isYueDu && !isWanXing" class="left-children">
          <template v-for="(c, idx) in data?.children" :key="c.id">
            <latex-text class="left-title" :text="filterTitle(c?.title, idx)"></latex-text>
            <!-- <div class="left-title" v-html="filterTitle(c?.title, idx)"></div> -->
          </template>
        </div>

        <!-- 阅读理解：子题题干 + 选项（纵向布局，参照小程序样式）；stemType===3 时右侧已有选项，左侧隐藏 -->
        <div v-if="isYueDu && yueDuList.length && data?.stemType !== 3" class="left-yuedu">
          <div v-for="(subQ, sIdx) in yueDuList" :key="sIdx" class="left-yuedu-item">
            <div class="left-yuedu-stem">
              <span class="left-yuedu-idx">{{ sIdx + 1 }}.</span>
              <div v-if="subQ.stem" class="left-yuedu-stem-text" v-html="subQ.stem"></div>
            </div>
            <div :class="['left-yuedu-opts', { vertical: !subQ.horizontal }]">
              <div v-for="(opt, oIdx) in subQ.options" :key="oIdx" class="left-yuedu-opt">
                <span class="left-yuedu-opt-label">{{ opt.label }}.</span>
                <div class="left-yuedu-opt-value" v-html="opt.value"></div>
              </div>
            </div>
          </div>
        </div>

        <!-- 完形填空：序号 + 选项（横向紧凑布局，无题干）；stemType===3 时右侧已有选项，左侧隐藏 -->
        <div v-if="isWanXing && yueDuList.length && data?.stemType !== 3" class="left-wanxing">
          <div v-for="(subQ, sIdx) in yueDuList" :key="sIdx" class="left-wanxing-row">
            <span class="left-wanxing-idx">{{ sIdx + 1 }}</span>
            <div class="left-wanxing-opts">
              <div v-for="(opt, oIdx) in subQ.options" :key="oIdx" class="left-wanxing-opt">
                <span class="left-wanxing-opt-label">{{ opt.label }}.</span>
                <div class="left-wanxing-opt-value" v-html="opt.value"></div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div ref="rightRef" class="right hidden_scroll">
        <!-- 批改结构 -->
        <div v-if="reportFlag" class="result-box">
          <div :class="['result', resultClass(data).class]">
            <div>我的答案</div>
            <div class="emoji-box">
              <div class="emoji">
                <Icon
                  v-if="
                    resultClass(data).icon &&
                    (0 === data?.actualScore || data?.actualScore === data?.score)
                  "
                  :name="resultClass(data).icon || ''"
                  width="48"
                ></Icon>
              </div>
              {{ resultClass(data).text }}
            </div>
          </div>
        </div>
        <!-- 得分 -->
        <div v-if="reportFlag" class="result-box">
          <div :class="['result', resultClass(data).class]">
            <div>我的得分</div>
            <div class="emoji-box">满分{{ data?.score }}分，实际得分{{ data?.actualScore }}分</div>
          </div>
        </div>
        <!-- 答题区域 -->
        <component
          :is="component"
          :reportFlag="Number(reportFlag)"
          class="answer-com"
          :titleId="data?.id"
          :stem="isCompositeStem ? data?.stem : undefined"
          :optionList="
            component === MultipleChoice || component === SingleChoice
              ? parsedOptionHtml || data?.optionList || undefined
              : data?.optionList || undefined
          "
          :answer="
            component === MultipleChoice || component === SingleChoice
              ? choiceAnswer
              : data?.answerSqs || data?.answer
          "
          :submitAnswer="data?.submitAnswer"
          :submitAnswerPic="data?.submitAnswerPic"
          :submitAnswerPicOriginal="data?.submitAnswerPicOriginal"
          :isAndroid="data?.isAndroid"
          :markAnswerPic="data?.markAnswerPic"
          :markAnswer="data?.markAnswer"
          :fillBlankNum="data?.fillBlankNum"
          :isDeadline="isDeadline"
          :uploadLoading="data?.uploadLoading"
          :uploadFile="uploadFile"
          :beforeUpload="beforeUpload"
          @submit="
            emit('submit', {
              ...$event,
              id: data?.jobStuTittleId || data?.itemId || data?.id,
            })
          "
          @handleTime="emit('handleTime', $event)"
          @showPic="handleShow"
          @inputChange="inputChange"
        >
          <template #markAnswer>
            <div v-if="reportFlag && data?.markAnswer" class="markAnswerPic">
              <div class="answer-box">
                <div class="answer-box-title">批改说明</div>
              </div>
              <div class="text-box">
                {{ data?.markAnswer }}
              </div>
            </div>
          </template>
        </component>

        <!-- 答案与解析 -->
        <div v-if="reportFlag">
          <div v-if="data?.knowledgeVoList?.length" class="answer-box">
            <div class="answer-box-title">知识点</div>
            <div class="answer-box-main knowledge-list">
              <span
                v-for="i in data.knowledgeVoList"
                :key="i.id"
                :class="['knowledge-list-item', i.videoList?.length ? 'active' : null]"
                :style="{
                  'background-image': i.videoList?.length
                    ? `url(${OSS_URL}/urm/doWork_curvedLine.svg)`
                    : '',
                }"
                @click="playVideo(i)"
              >
                {{ i.name }}
              </span>
            </div>
          </div>
          <div v-if="echartsData.xData.length" class="answer-box">
            <div class="answer-box-title">答题统计</div>
            <div class="answer-box-echarts">
              <EchartsBar
                ref="echartsRef"
                :data="echartsData"
                yName="（人）"
                @handleBarClick="handleBarClick"
              ></EchartsBar>
            </div>
          </div>
          <div v-if="data?.answerHtml || data?.answer" class="answer-box">
            <div class="answer-box-title">参考答案</div>
            <AiText class="answer-box-main" :text="data?.answerHtml || data?.answer || ''" />
          </div>
          <!-- 暂时隐藏 data.titleAnalyzeJson -->
          <div
            v-if="explanationText || data?.titleAnalyzePicture"
            class="answer-box"
            style="margin-top: 60px"
          >
            <div class="answer-box-title">解析</div>
            <div v-if="explanationText" class="answer-box-main analyze analyze-title">
              <AiText class="titleAnalyze" :text="explanationText" />
            </div>
            <div v-if="data?.titleAnalyzePicture" class="answer-box-main analyze analyze-pic">
              <div
                v-for="i in data.titleAnalyzePicture.split(',')"
                :key="i"
                class="titleAnalyzePicture"
                @click="handleShow(i)"
              >
                <img :src="i" />
              </div>
            </div>
          </div>
          <div v-if="showAiAnswer && data?.aiAnswer" class="answer-box" style="margin-top: 60px">
            <div class="answer-box-title">AI答案</div>
            <div class="answer-box-main analyze analyze-title">
              <AiText class="titleAnalyze" :text="data?.aiAnswer || ''" />
            </div>
          </div>
          <div v-if="showAiAnswer && data?.aiAnalyze" class="answer-box" style="margin-top: 60px">
            <div class="answer-box-title">AI点评</div>
            <div class="answer-box-main analyze analyze-title">
              <AiText class="titleAnalyze" :text="data?.aiAnalyze || ''" />
            </div>
          </div>
        </div>
        <div v-else class="empty"></div>
      </div>
    </div>
    <ImgView v-model="imgDia.show" :url="imgDia.url"></ImgView>
    <mj-dialog v-model="xlDia.show" :hide-close="true" :hide-cancel="true" title="对应学员">
      <div class="stu_list">
        <div v-for="i in xlDia.data" :key="i.id" class="stu_list-item">
          {{ i.name }}
        </div>
      </div>
    </mj-dialog>
    <VideoFullBox
      v-model:show="videoDia.show"
      :knowledge="videoDia.knowledge"
      :data="{
        subjectId: props.data?.subjectId || '',
        resourceType: 0,
        origin: 2,
      }"
    ></VideoFullBox>
    <Feedback v-model:show="feedbackDia.show" :data="feedbackDia.data"></Feedback>
    <AiReplyDia
      v-model="aiReplyVisible"
      :subject-id="props.data?.subjectId"
      :question-id="props.data?.id"
    />
  </div>
</template>
<style lang="scss">
.question-item {
  .fill-blank {
    display: inline-block;
    width: 5vh;
    border-bottom: 1px solid $aux-color;
  }

  .left-title {
    sub,
    sup {
      font-size: inherit;
      vertical-align: baseline;
    }

    table {
      width: auto !important;
      max-width: 100%;

      td {
        width: auto !important;
      }
    }
  }

  .xkw-math-img {
    height: 1em;
    vertical-align: middle;
  }
}
</style>
<style scoped lang="scss">
.question-item {
  width: 100%;
  height: 100%;
  // padding: 36px;
  display: flex;
  flex-direction: column;
  align-items: center;
  // justify-content: center;

  .top {
    position: relative;
    width: 100%;
    z-index: 2;

    .difficulty-start_box {
      width: 400px;
      position: absolute;
      z-index: 2;
      :deep(.difficulty-start) {
        background: transparent;
        .text {
          color: #666;
        }
      }
    }

    .title-type {
      width: fit-content;
      padding: 0 30px;
      height: 5.5vh;
      background-color: #d6f2ff;
      margin: 0 auto;
      border-radius: 0 0 2.67vh 2.67vh;
      text-align: center;
      font-family: OPPOSans;
      font-size: 2.5vh;
      line-height: 5.5vh;
      color: $font-color;
    }
    .right-top {
      position: absolute;
      padding-right: 40px;
      top: 0;
      right: 0;
      z-index: 2;
      display: flex;
      align-items: center;
      gap: 20px;

      .feedback {
        color: #fff;
      }
    }
  }

  .main-box {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    padding: 2.67vh;
    display: flex;
    align-items: center;

    .collapse-btn {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      z-index: 99;
      width: 50px !important;
      height: 50px !important;
      border-radius: 50% !important;
      padding: 0 !important;
      display: flex;
      justify-content: center;
      align-items: center;
      transition: all 0.3s;

      :deep(.mj-button-text) {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 100%;
      }

      :deep(img) {
        display: none !important;
      }
    }

    &.collapsed {
      &::before {
        opacity: 0;
      }
      .left {
        width: 100%;
        padding-right: 0;
      }
      .right {
        width: 0;
        padding: 0;
        opacity: 0;
        overflow: hidden;
      }
      .collapse-btn {
        left: auto;
        right: 0;
        border-radius: 20px 0 0 20px !important;
        width: 50px !important;
        height: 50px !important;
        transform: translateY(-50%);
        box-shadow: -2px 0 8px 0 rgba(0, 0, 0, 0.15);

        &:hover {
          width: 60px !important;
        }
      }
    }

    &::before {
      position: absolute;
      left: 50%;
      bottom: 2.5vh;
      transform: translate(-50%);
      content: '';
      display: block;
      width: 6px;
      height: calc(100% - 120px);
      border-radius: 0.5vh;
      background: repeating-linear-gradient(
        to bottom,
        #cdd5ff,
        #cdd5ff 8px,
        transparent 10px,
        transparent 20px /* 线条间隔 */
      );
      transition: opacity 0.3s;
    }
  }

  .left {
    width: calc(50% - 3px);
    height: 100%;
    padding-right: 48px;

    word-break: normal;
    word-wrap: break-word;
    overflow-y: auto;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    &-subType {
      color: #666;
      font-family: 'OPPO Sans';
      font-size: 2.67vh;
      font-style: normal;
      font-weight: 400;
      line-height: 4vh; /* 150% */
      margin-bottom: 2vh;
    }
    &-title {
      color: $font-color;
      font-family: 'OPPO Sans';
      font-size: 2.67vh;
      font-style: normal;
      font-weight: 400;
      line-height: 1.8em;
      padding-left: 15px;
    }
    &-voice {
      padding-left: 40px;
      margin-top: 2vh;
    }
    &-children {
      padding-left: 40px;
      color: $font-color;
      font-family: 'OPPO Sans';
      font-size: 2.67vh;
      font-style: normal;
      font-weight: 400;
      line-height: 4vh; /* 150% */
      margin-top: 1.33vh;
      .left-title {
        padding-left: 0;
      }
    }

    // 阅读理解：子题题干 + 选项（纵向布局，参照小程序样式）
    .left-yuedu {
      margin-top: 1.33vh;
      padding: 0 15px;

      .left-yuedu-item {
        margin-bottom: 1.33vh;
        padding: 1.2vh 1.5vh;
        background: rgba(79, 142, 247, 0.04);
        border-radius: 1vh;
        border-left: 4px solid #8fb5ff;

        &:last-child {
          margin-bottom: 0;
        }
      }

      .left-yuedu-stem {
        display: flex;
        align-items: flex-start;
        margin-bottom: 0.5vh;

        .left-yuedu-idx {
          font-family: $font-special;
          font-size: 2.67vh;
          font-weight: 700;
          color: #4f8ef7;
          margin-right: 6px;
          flex-shrink: 0;
          line-height: 1.6;
        }

        .left-yuedu-stem-text {
          flex: 1;
          font-size: 2.67vh;
          color: $font-color;
          line-height: 1.6;

          :deep(img) {
            max-width: 100%;
            height: auto;
          }
        }
      }

      .left-yuedu-opts {
        padding-left: 2.5vh;
        display: flex;
        flex-wrap: wrap;
        gap: 2px 16px;

        &.vertical {
          flex-direction: column;
          gap: 2px;

          .left-yuedu-opt {
            width: 100%;
          }
        }

        .left-yuedu-opt {
          display: flex;
          align-items: flex-start;
          line-height: 1.6;

          .left-yuedu-opt-label {
            font-size: 2.67vh;
            color: #8f9df7;
            font-weight: 600;
            margin-right: 4px;
            flex-shrink: 0;
          }

          .left-yuedu-opt-value {
            font-size: 2.67vh;
            color: $font-color;

            :deep(img) {
              max-width: 100%;
              height: auto;
            }
          }
        }
      }
    }

    // 完形填空：序号 + 选项（横向紧凑，无题干）
    .left-wanxing {
      margin-top: 1.33vh;
      padding: 0 15px;

      .left-wanxing-row {
        display: flex;
        align-items: flex-start;
        gap: 8px;
        margin-bottom: 0.8vh;

        &:last-child {
          margin-bottom: 0;
        }
      }

      .left-wanxing-idx {
        font-family: $font-special;
        font-size: 2.67vh;
        font-weight: 700;
        color: #4f8ef7;
        flex-shrink: 0;
        line-height: 1.6;
      }

      .left-wanxing-opts {
        flex: 1;
        display: flex;
        flex-wrap: wrap;
        gap: 4px 16px;
      }

      .left-wanxing-opt {
        display: flex;
        align-items: flex-start;
        line-height: 1.6;

        .left-wanxing-opt-label {
          font-size: 2.67vh;
          color: #8f9df7;
          font-weight: 600;
          margin-right: 4px;
          flex-shrink: 0;
        }

        .left-wanxing-opt-value {
          font-size: 2.67vh;
          color: $font-color;

          :deep(img) {
            max-width: 100%;
            height: auto;
          }
        }
      }
    }
  }
  .right {
    width: calc(50% - 3px);
    height: 100%;
    padding-left: 48px;
    padding-top: 1.33vh;
    padding-right: 15px;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    .result-box {
      width: 100%;
      height: 4vh;
      margin-bottom: 2vh;
    }
    .result {
      padding: 0 20px 0 32px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      position: relative;
      color: $font-color;
      font-family: $font-special;
      font-size: 2.67vh;
      font-style: normal;
      font-weight: 400;
      line-height: 4vh; /* 150% */
      border-radius: 0.33vh;
      &::before {
        content: '';
        width: 12px;
        height: 100%;
        flex-shrink: 0;
        position: absolute;
        top: 0;
        left: 0;
        background-color: #669cfe;
        border-radius: 0 1vh 1vh 0;
      }
      &.error {
        background: linear-gradient(90deg, rgba(255, 191, 191, 0) 0%, #ffbfbf 100%);
      }
      &.success {
        background: linear-gradient(90deg, rgba(221, 255, 140, 0) 0%, #ddff8c 100%);
      }
      &.empty {
        background: linear-gradient(90deg, rgba(255, 191, 191, 0) 0%, #ffbfbf 100%);
      }
      &.wait {
        background: linear-gradient(90deg, rgba(190, 213, 254, 0) 0%, #bed5fe 100%);
      }
      &.info {
        background: linear-gradient(90deg, rgba(190, 213, 254, 0) 0%, #bed5fe 100%);
      }
      .emoji-box {
        display: flex;
        align-items: center;
        .emoji {
          width: 48px;
          height: 4vh;
          margin-right: 16px;
        }
      }
    }

    .answer-box {
      margin-top: 4vh;
      &-title {
        padding: 0 20px 0 32px;
        position: relative;
        color: $font-color;
        font-family: 'OPPO Sans';
        font-size: 2.67vh;
        font-style: normal;
        font-weight: 400;
        line-height: 4vh; /* 150% */
        border-radius: 0.33vh;
        margin-bottom: 2vh;
        &::before {
          content: '';
          width: 12px;
          height: 100%;
          flex-shrink: 0;
          position: absolute;
          top: 0;
          left: 0;
          background-color: #669cfe;
          border-radius: 0 1vh 1vh 0;
        }
      }
      &-echarts {
        height: 28.33vh;
      }
      &-main {
        color: $font-color;
        font-family: 'OPPO Sans';
        font-size: 2.67vh;
        font-style: normal;
        font-weight: 400;
        line-height: 4vh; /* 150% */
        padding-left: 32px;
        width: 100%;
        &.analyze {
          // padding-left: 0;
          width: 100%;
          &.analyze-pic {
            margin-top: 2vh;
            img {
              max-width: 100%;
              max-height: 66.67vh;
              object-fit: contain;
            }
            .titleAnalyzePicture {
              margin-bottom: 1vh;
              &:last-child {
                margin-bottom: 0;
              }
            }
          }
          &.analyze-title {
            margin-top: 2vh;

            .titleAnalyze {
              color: $font-color;
              font-family: 'OPPO Sans';
              font-size: 2.67vh;
              font-style: normal;
              font-weight: 400;
              line-height: 4vh; /* 150% */
            }
          }
        }
      }

      .knowledge-list {
        &-item {
          margin-right: 8px;
          position: relative;
          display: inline-block;
          padding-bottom: 1vh;

          &:last-child {
            margin-right: 0;
          }
          &.active {
            cursor: pointer;
            color: #8409d6;
            background-position: -10px bottom;
            background-size: 19px 12px;
            background-repeat: repeat no-repeat;
          }
        }
      }
    }
    .text-box {
      font-size: 2.67vh;
      font-style: normal;
      font-weight: 400;
      line-height: 4vh; /* 150% */
      padding-left: 48px;
    }
  }
}
:deep(.mj-dialog) {
  width: 1300px;
}
.mj-dialog {
  .stu_list {
    display: flex;
    align-items: start;
    flex-wrap: wrap;
    height: 100%;
    @include hidden_scroll;
    &-item {
      border-radius: 3.5vh;
      border: 0.17vh solid $font-color;
      padding: 1.33vh 32px;
      color: $font-color;
      text-align: center;
      font-family: OPPOSans;
      font-size: 2.67vh;
      margin: 1vh;
    }
  }
}
</style>
