<template>
  <div v-loading="loading" class="questionList-wrapper">
    <div class="container">
      <div class="basic-info">
        <h3>
          <span v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && visitInfo.SubjectCode" style="margin-right:5px;">
            {{ visitInfo.SubjectCode }} 
          </span>
          <span>
            <span v-if="taskInfo && !taskInfo.IsReadingShowSubjectInfo">
              {{ $t('trials:reading:title:taskName') }}
            </span>
            {{ visitInfo.TaskBlindName }}
          </span>
        </h3>
        <div v-if="readingTaskState < 2">
          <el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')"
            placement="bottom">
            <i class="el-icon-refresh-left" @click="resetForm" />
          </el-tooltip>
        </div>
      </div>
      <el-form v-if="taskInfo && rerender" ref="questions" size="small" :model="questionForm" class="ecrf-form">
        <template v-if="rerender">
          <QuestionFormItem v-for="question of questions" :key="question.Id" :visit-task-id="visitTaskId"
            :isNoneDicom="isNoneDicom" :question="question" :question-form="questionForm"
            :reading-task-state="readingTaskState" :criterion-id="criterionId" :calculation-list="calculationList"
            :question-mark-info-list="questionMarkInfoList" :questions-mark-status="questionsMarkStatus"
            :questionsSegmentMarkStatus="questionsSegmentMarkStatus" :is-baseline="isBaseLineTask"
            @resetFormItemData="resetFormItemData" @setFormItemData="setFormItemData" @getQuestions="getQuestions"
            @operateImageMarker="operateImageMarker" @unBindAnnotationToQuestion="unBindAnnotationToQuestion"
            @handleReadingChart="handleReadingChart" @saveSegmentBindingAndAnswer="saveSegmentBindingAndAnswer" />
        </template>

        <el-form-item v-if="readingTaskState < 2">
          <div class="action-bar">
            <!-- <i class="el-icon-warning feedback-icon" @click="openFeedBackTable"
              :style="{ color: taskInfo && taskInfo.IsExistUnprocessedFeedback ? '#ffeb3b' : '#fff' }" /> -->
            <el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :disabled="isTableVisible"
              type="primary" @click="skipTask">
              {{ $t('trials:readingReport:button:skip') }}
            </el-button>
            <el-button type="primary" :loading="submitLockAction === 'save'"
              :disabled="isTableVisible || isSaved || !!submitLockAction" @click="handleSave">
              {{ $t('common:button:save') }}
            </el-button>
            <el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :loading="submitLockAction === 'submit'"
              :disabled="isTableVisible || !!submitLockAction"
              type="primary" @click="handleSubmit">
              {{ $t('common:button:submit') }}
            </el-button>
          </div>
        </el-form-item>
      </el-form>
    </div>

    <!-- 签名框 -->
    <el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
      custom-class="base-dialog-wrapper">
      <div slot="title">
        <span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
        <span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${currentUser})` }}</span>
      </div>
      <SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
    </el-dialog>
  </div>

</template>

<script>

import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, verifyVisitTaskQuestions, getQuestionCalculateRelation, saveTaskQuestion } from '@/api/trials'
import { setSkipReadingCache, resetReadingTask, saveTableQuestionMark, saveAnswerAndBindingNoneDicomMark, changePlottingScaleChangeAnswer, getSegmentBindingList, saveSegmentBindingAndAnswer, getSegmentList, getSegmentationList } from '@/api/reading'
import const_ from '@/const/sign-code'
import QuestionFormItem from './QuestionFormItem'
import SignForm from '@/views/trials/components/newSignForm'
import store from '@/store'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import {
  utilities as csUtils
  // getEnabledElementByIds
} from '@cornerstonejs/core'
export default {
  name: 'EcrfList',
  components: {
    QuestionFormItem,
    SignForm
  },
  props: {
    visitInfo: {
      type: Object,
      required: true
    },
    readingTaskState: {
      type: Number,
      required: true
    },
    isNoneDicom: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      trialId: '',
      criterionId: '',
      visitTaskId: '',
      loading: false,
      questions: [],
      questionForm: {},
      publicQuestions: [],
      signVisible: false,
      signCode: null,
      currentUser: zzSessionStorage.getItem('userName'),
      activeName: 0,
      classArr: [],
      calculationList: [],
      taskInfo: null,
      isBaseLineTask: false,
      rerender: true,
      questionMarkInfoList: [],
      operateStateEnum: null, // 0：绑定；1：标记；2：查看；3：更改；4：移除；5：保存；6：更改数值内容；
      operateQuestionId: '',
      operateQuestionName: '',
      operateRowId: '',
      operateParentQsId: '',
      isTableQuestion: false,
      imageTool: '',
      imageToolAttribute: '',
      questionsMarkStatus: {},
      questionsSegmentMarkStatus: {},
      digitPlaces: 2,
      questionImageToolAttributeInfo: {},
      unSaveTargets: [],
      isTableVisible: false,
      isSaved: false,
      submitLockAction: ''
    }
  },
  mounted() {
    window.addEventListener('message', this.receiveMsg)
    this.trialId = this.$route.query.trialId
    this.visitTaskId = this.visitInfo.VisitTaskId
    this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
    this.isBaseLineTask = this.taskInfo.IsBaseLine
    this.criterionId = this.taskInfo.TrialReadingCriterionId
    const digitPlaces = Number(localStorage.getItem('digitPlaces'))
    this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
    this.getQuestionCalculateRelation()
    this.getQuestions(true)
    this.initSegmentBinding()
    DicomEvent.$on('opentableCol', (data) => {
      let { visible } = data
      this.isTableVisible = visible
    })
  },
  computed: {
    isEN() {
      return this.$i18n.locale !== 'zh'
    },
  },
  methods: {
    normalizeQuestionAnswer(question, answer) {
      if (answer === null || answer === undefined || answer === '') return answer
      if (question.Type === 'select' && question.OptionTypeEnum === 1) return answer
      if (question.DictionaryCode && ['radio', 'select'].includes(question.Type)) {
        return String(answer)
      }
      if (question.Type === 'class' && question.ClassifyShowType === 3 && question.DictionaryCode) {
        return String(answer)
      }
      return answer
    },
    handleReadingChart(e) {
      this.$emit('handleReadingChart', e)
    },
    async getQuestions(isInit) {
      this.loading = true
      try {
        const param = {
          visitTaskId: this.visitTaskId,
          IsDicomReading: !this.isNoneDicom
        }
        const res = await getCustomTableQuestionAnswer(param)
        if (res.IsSuccess) {
          // this.readingTaskState = res.OtherInfo.ReadingTaskState
          res.Result.SinglePage.map((v) => {
            if (v.Type === 'group' && v.Childrens.length === 0) return
            if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
              this.$set(this.questionForm, v.Id, this.normalizeQuestionAnswer(v, v.Answer))
            }
            if (v.Type === 'table' || v.Type === 'basicTable') {
              this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
            }
            if (v.Type === 'class') {
              this.classArr.push({ triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType })
            }
            if (v.Type === 'number') {
              this.$set(this.questionForm, v.Id, isNaN(parseFloat(v.Answer)) ? v.Answer : parseFloat(v.Answer).toFixed(this.digitPlaces))
              if (v.ImageToolAttribute) {
                this.$set(this.questionImageToolAttributeInfo, v.Id, v.ImageToolAttribute)
              }
            }
            if (v.Childrens.length > 0) {
              this.setChild(v.Childrens)
            }
          })
          this.questions = res.Result.SinglePage
          if (this.isNoneDicom) {
            this.$emit("setIsHaveBindingQuestion", res.OtherInfo.IsHaveBindingQuestion)
          }
          this.questionsMarkStatus = {}
          this.questionMarkInfoList = []
          this.questionMarkInfoList = res.OtherInfo.QuestionMarkInfoList.map(i => {
            if (i.RowId) {
              this.$set(this.questionsMarkStatus, `${i.RowId}_${i.TableQuestionId}`, { isMarked: i.MeasureData !== '', isSaved: true, OrderMarkName: i.OrderMarkName })
            } else if (i.QuestionId) {
              this.$set(this.questionsMarkStatus, i.QuestionId, { isMarked: i.MeasureData !== '', isSaved: true, OrderMarkName: i.OrderMarkName })
            }
            if (typeof i.MeasureData === 'string' && i.MeasureData) {
              i.MeasureData = JSON.parse(i.MeasureData)
            }
            return i
          })
          if (!isInit) {
            this.$emit('resetAnnotations', this.visitTaskId)
          }
          this.loading = false
        }
      } catch (e) {
        console.log(e)
        this.loading = false
      }
    },
    setChild(obj) {
      obj.forEach(i => {
        if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
          this.$set(this.questionForm, i.Id, this.normalizeQuestionAnswer(i, i.Answer))
        }
        if (i.Type === 'select' && i.OptionTypeEnum === 1) {
          this.$set(this.questionForm, i.Id, i.Answer ? JSON.parse(i.Answer) : [])
        }
        if (i.Type === 'table' || i.Type === 'basicTable') {
          i.TableQuestions.Questions.forEach(o => {
            if (o.Type === 'number') {
              i.TableQuestions.Answers.forEach((ite, index) => {
                this.$set(i.TableQuestions.Answers[index], o.Id, isNaN(parseFloat(i.TableQuestions.Answers[index][o.Id])) ? i.TableQuestions.Answers[index][o.Id] : parseFloat(i.TableQuestions.Answers[index][o.Id]).toFixed(this.digitPlaces))
              })
              this.$set(this.questionImageToolAttributeInfo, o.Id, o.ImageToolAttribute)
            }
            if (o.Type === 'select' && o.OptionTypeEnum === 1) {
              i.TableQuestions.Answers.forEach((ite, index) => {
                this.$set(i.TableQuestions.Answers[index], o.Id, i.TableQuestions.Answers[index][o.Id] ? JSON.parse(i.TableQuestions.Answers[index][o.Id]) : [])
              })
            }
            if ((o.DictionaryCode && ['radio', 'select'].includes(o.Type) && o.OptionTypeEnum !== 1) || (o.Type === 'class' && o.ClassifyShowType === 3 && o.DictionaryCode)) {
              i.TableQuestions.Answers.forEach((ite, index) => {
                this.$set(i.TableQuestions.Answers[index], o.Id, this.normalizeQuestionAnswer(o, i.TableQuestions.Answers[index][o.Id]))
              })
            }
          })
          this.$set(this.questionForm, i.Id, i.TableQuestions.Answers)
        }
        if (i.Type === 'class') {
          this.classArr.push({ triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType })
        }
        if (i.Type === 'number') {
          this.$set(this.questionForm, i.Id, isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(this.digitPlaces))
          if (i.ImageToolAttribute) {
            this.$set(this.questionImageToolAttributeInfo, i.Id, i.ImageToolAttribute)
          }
        }
        if (i.Childrens && i.Childrens.length > 0) {
          this.setChild(i.Childrens)
        }
      })
    },
    async getQuestionCalculateRelation() {
      try {
        const res = await getQuestionCalculateRelation({ TrialReadingCriterionId: this.criterionId })
        this.calculationList = res.Result
      } catch (e) {
        console.log(e)
      }
    },
    async validateBeforeSave() {
      const valid = await this.$refs['questions'].validate().catch(() => false)
      if (!valid) return false
      const hasUnsavedAnnotation = this.verifyAnnotationIsSave()
      if (!hasUnsavedAnnotation) return true
      const confirm = await this.$confirm(this.$t('trials:reading:confirm:AnnotationNotSave'), this.$t('system:menu:confirm:title:warning'), {
          type: 'warning'
        }).catch(() => false)
      return confirm === 'confirm'
    },
    async saveQuestions(isMsg) {
      this.loading = true
      try {
        var answers = []
        for (const k in this.questionForm) {
          if (this.questionForm[k] instanceof Array) {
            if (this.questionForm[k].length > 0 && Object.prototype.toString.call(this.questionForm[k][0]) === '[object String]') {
              answers.push({ id: k, answer: JSON.stringify(this.questionForm[k]) })
            }
          } else {
            answers.push({ id: k, answer: this.questionForm[k] })
          }
        }
        var params = {
          visitTaskId: this.visitTaskId,
          answers: answers
        }
        const res = await changeDicomReadingQuestionAnswer(params)
        if (res.IsSuccess) {
          if (isMsg) {
            this.isSaved = true
            this.$message.success(this.$t('common:message:savedSuccessfully'))
          }
          return true
        }
        return false
      } catch (e) {
        return false
      } finally {
        this.loading = false
      }
    },
    async handleSave(isMsg = true) {
      if (this.submitLockAction) return false
      this.submitLockAction = 'save'
      try {
        const isValid = await this.validateBeforeSave()
        if (!isValid) return false
        return await this.saveQuestions(isMsg)
      } finally {
        this.submitLockAction = ''
      }
    },
    async handleSubmit() {
      if (this.submitLockAction) return false
      this.submitLockAction = 'submit'
      try {
        const isValid = await this.validateBeforeSave()
        if (!isValid) return false
        const isSaveSuccess = await this.saveQuestions(false)
        if (!isSaveSuccess) return false
        await verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId })
        const { ImageAssessmentReportConfirmation } = const_.processSignature
        this.signCode = ImageAssessmentReportConfirmation
        this.signVisible = true
        return true
      } finally {
        this.submitLockAction = ''
      }
    },
    // 关闭签名框
    closeSignDialog(isSign, signInfo) {
      if (isSign) {
        this.signConfirm(signInfo)
      } else {
        this.signVisible = false
      }
    },
    // 签名并确认
    async signConfirm(signInfo) {
      this.loading = true
      var answers = []
      for (const k in this.questionForm) {
        if (this.questionForm[k] instanceof Array) {
          if (this.questionForm[k].length > 0 && Object.prototype.toString.call(this.questionForm[k][0]) === '[object String]') {
            answers.push({ id: k, answer: JSON.stringify(this.questionForm[k]) })
          }
        } else {
          answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] })
        }
      }
      var params = {
        data: {
          trialId: this.trialId,
          visitTaskId: this.visitTaskId,
          readingQuestionCriterionTrialId: this.criterionId,
          answerList: answers
        },
        signInfo: signInfo
      }
      try {
        const res = await submitVisitTaskQuestionsInDto(params)
        this.loading = false
        if (res.IsSuccess) {
          this.$message.success(this.$t('common:message:savedSuccessfully'))
          this.isEdit = false
          this.$refs['signForm'].btnLoading = false
          this.signVisible = false
          this.$emit('setReadingTaskState', 2)
          window.opener.postMessage('refreshTaskList', window.location)
          const confirm = await this.$confirm(
            this.$t('trials:noneDicoms:message:msg1'),
            {
              type: 'warning',
              distinguishCancelAndClose: true
            }
          )
          if (confirm !== 'confirm') return
          window.location.reload()
        }
      } catch (e) {
        this.loading = false
        this.$refs['signForm'].btnLoading = false
      }
    },
    async skipTask() {
      try {
        let isSaved = this.verifyAnnotationIsSave()
        if (isSaved) {
          let confirm = this.$confirm(this.$t('trials:reading:confirm:AnnotationNotSave'), this.$t('system:menu:confirm:title:warning'), {
            type: 'warning'
          })
          if (!confirm) return false
        }
        // 是否确认跳过？
        const confirm = await this.$confirm(
          this.$t('trials:readingReport:message:skipConfirm'),
          {
            type: 'warning',
            distinguishCancelAndClose: true
          }
        )
        if (confirm !== 'confirm') return
        this.loading = true
        const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
        this.loading = false
        if (res.IsSuccess) {
          window.location.reload()
        }
      } catch (e) {
        this.loading = false
        console.log(e)
      }
    },
    resetFormItemData(v) {
      this.questionForm[v] = null
    },
    setFormItemData(obj) {
      this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
      this.classArr.map(i => {
        if (i.triggerId === obj.key) {
          let answer = null
          const list = JSON.parse(i.classifyAlgorithms)
          if (i.classifyType === 0) {
            const o = list.find(v => {
              return (
                parseFloat(obj.val) >= parseFloat(v.gt) &&
                parseFloat(obj.val) < parseFloat(v.lt)
              )
            })
            answer = o ? o.label : 'NE'
          } else if (i.classifyType === 1) {
            const o = list.find(v => {
              return v.val.includes(obj.val)
            })
            answer = o ? o.label : null
          }
          this.$set(this.questionForm, i.classId, answer)
        }
      })
    },

    verifyAnnotationIsBound(annotation) {
      const i = this.questionMarkInfoList.findIndex(i => i.MeasureData && i.MeasureData.annotationUID === annotation.annotationUID)
      return i > -1
    },
    verifyFileIsBound(annotation) {
      const i = this.questionMarkInfoList.findIndex(i => i.MeasureData && i.MeasureData.noneDicomFileId === annotation.noneDicomFileId)
      return i > -1
    },
    async operateImageMarker(obj) {
      const STATE = {
        BIND: 0,       // 绑定标记
        ADD: 1,        // 添加标记
        VIEW: 2,       // 查看标记
        CHANGE: 3,     // 更改标记
        REMOVE: 4,     // 移除标记
        SAVE_OUTER: 5, // 保存外层标记
        UPDATE: 6,     // 更改数值内容
        SAVE_TABLE: 7,  // 保存表格标记
        BIND_SEGMENT: 21, // 绑定分割标记
        CHANGE_SEGMENT: 22, // 更改分割标记
        VIEW_SEGMENT: 23, // 查看分割标记
        REMOVE_SEGMENT: 24, // 移除分割标记
      }
      // console.log(obj, 'obj')
      const { question, operateStateEnum, rowId, answer } = obj
      const { Id, IsTableQuestion, ImageTool, ImageToolAttribute, ParentQsId, RowId, QuestionName, QuestionEnName } = question

      Object.assign(this, {
        operateStateEnum,
        isTableQuestion: !!IsTableQuestion,
        imageTool: ImageTool,
        imageToolAttribute: ImageToolAttribute,
        operateQuestionId: Id,
        operateQuestionName: this.isEN ? QuestionEnName : QuestionName,
        operateRowId: RowId,
        operateParentQsId: ParentQsId,
      })
      const stateHandlers = {
        [STATE.BIND]: () => this.$emit('setReadingToolPassive'),
        [STATE.ADD]: () => this.$emit('setReadingToolActive', ImageTool),
        [STATE.VIEW]: this.handleViewAnnotation,
        [STATE.CHANGE]: () => this.$emit('setReadingToolPassive'),
        [STATE.REMOVE]: this.handleRemoveAnnotation,
        [STATE.SAVE_OUTER]: this.isNoneDicom ? this.handleSaveNoneDicomOuterQuestions : this.handleSaveOuterQuestions,
        [STATE.UPDATE]: this.handleUpdateValue,
        [STATE.SAVE_TABLE]: this.isNoneDicom ? this.handleSaveNoneDicomTableQuestions : this.handleSaveTableQuestions,
        [STATE.BIND_SEGMENT]: this.handleBindSegment,
        [STATE.CHANGE_SEGMENT]: this.handleBindSegment,
        [STATE.VIEW_SEGMENT]: this.handleViewSegment,
        [STATE.REMOVE_SEGMENT]: this.handleRemoveSegment,
      }

      const handler = stateHandlers[operateStateEnum]
      handler && await handler.call(this, obj)
    },
    async handleViewSegment(obj) {
      try {
        let o = {}
        if (this.isTableQuestion) {
          o.TableQuestionId = this.operateQuestionId
          o.RowId = this.operateRowId
        } else {
          o.QuestionId = this.operateQuestionId
        }
        let list = await this.getSegmentBindingList(o)
        if (list && list.length > 0) {
          let segment = await this.getSegmentList(list[0].SegmentId)
          if (segment[0].SegmentJson) {
            let obj = JSON.parse(segment[0].SegmentJson)
            segment[0].stats = obj.stats
            segment[0].bidirectional = obj.bidirectional
            segment[0].segmentationId = segment[0].SegmentationId
            segment[0].segmentIndex = segment[0].SegmentNumber
          }
          let segmentGroup = await this.getSegmentationList(list[0].SegmentationId)
          this.$emit('viewCustomAnnotationSeries', {
            visitTaskId: this.visitTaskId,
            segment: segment[0],
            segmentGroup: segmentGroup[0]
          })
        }

      } catch (err) {
        console.log(err)
      }
    },
    handleBindSegment(obj) {
      this.$emit("openSegmentForm", { visitInfo: this.visitInfo, operateStateEnum: obj.operateStateEnum, isTableQuestion: this.isTableQuestion, operateQuestionId: this.operateQuestionId, operateRowId: this.operateRowId })
    },
    handleSegmentSave(obj) {
      let imageToolAttribute = this.imageToolAttribute
      let answer = ''
      if (imageToolAttribute === 'length' || imageToolAttribute === 'width') {
        let s = {
          length: "maxMajor",
          width: 'maxMinor'
        }
        if (!obj.bidirectional || !obj.bidirectional.maxMajor) return this.$confirm(this.$t("segment:error:notValue"))
        answer = obj.bidirectional[s[imageToolAttribute]] ? Number(obj.bidirectional[s[imageToolAttribute]]).toFixed(this.digitPlaces) : ''
      } else {
        if (!obj.stats || !obj.stats[imageToolAttribute] || obj.stats[imageToolAttribute].value === null) return this.$confirm(this.$t("segment:error:notValue"))
        answer = obj.stats[imageToolAttribute] ? Number((obj.stats[imageToolAttribute]).value).toFixed(this.digitPlaces) : ''
      }
      let o = {
        Answer: answer,
        SegmentId: obj.Id,
        SegmentationId: obj.SegmentationId,
        QuestionId: this.isTableQuestion ? this.operateParentQsId : this.operateQuestionId,
        RowId: this.isTableQuestion ? this.operateRowId : null,
        TableQuestionId: this.isTableQuestion ? this.operateQuestionId : null,
        VisitTaskId: this.visitTaskId,
      }
      if (this.isTableQuestion) {
        return DicomEvent.$emit('setTableQuestionAnswer', { id: this.operateQuestionId, answer, ParentQsId: this.operateParentQsId, data: o })
      } else {
        this.$set(this.questionForm, this.operateQuestionId, answer)
      }
      this.saveSegmentBindingAndAnswer([o])
    },
    // 删除问题与分割标记绑定
    async handleRemoveSegment(obj) {
      const { question } = obj
      let confirm = await this.$confirm(this.$t('segment:confirm:sureDelete'))
      if (!confirm) return false
      if (this.isTableQuestion) {
        this.questionForm[question.ParentQsId].some((item, index) => {
          if (item.RowId === question.RowId) {
            this.$set(this.questionForm[question.ParentQsId][index], question.Id, '')
          }
          return item.RowId === question.RowId
        })
      } else {
        this.$set(this.questionForm, question.Id, '')
      } 
      let o = {
        Answer: '',
        SegmentId: null,
        SegmentationId: null,
        QuestionId: this.isTableQuestion ? this.operateParentQsId : this.operateQuestionId,
        RowId: this.isTableQuestion ? this.operateRowId : null,
        TableQuestionId: this.isTableQuestion ? this.operateQuestionId : null,
        VisitTaskId: this.visitTaskId,
      }
      this.saveSegmentBindingAndAnswer([o])
    },
    // 添加分割标记与问题绑定关系
    async saveSegmentBindingAndAnswer(list) {
      try {
        let data = {
          VisitTaskId: this.visitTaskId,
          BindingList: list
        }
        let res = await saveSegmentBindingAndAnswer(data)
        if (res.IsSuccess) {
          this.initSegmentBinding()
        }
      } catch (err) {
        console.log(err)
      }
    },
    // 初始化分割标记与问题绑定关系
    async initSegmentBinding() {
      try {
        let list = await this.getSegmentBindingList()
        this.questionsSegmentMarkStatus = {}
        list.forEach(item => {
          if (item.TableQuestionId && item.RowId) {
            this.$set(this.questionsSegmentMarkStatus, `${item.RowId}_${item.TableQuestionId}`, { SegmentId: item.SegmentId, SegmentationName: item.SegmentationName, SegmentName: item.SegmentName, })
          } else {
            this.$set(this.questionsSegmentMarkStatus, item.QuestionId, { SegmentId: item.SegmentId, SegmentationName: item.SegmentationName, SegmentName: item.SegmentName, })
          }
        })
      } catch (err) {
        console.log(err)
      }
    },
    // 获取当前任务分割标记与问题绑定关系
    async getSegmentBindingList(param = {}) {
      try {
        let data = {
          VisitTaskId: this.visitTaskId,
          PageSize: 9999,
          PageIndex: 1,
        }
        data = Object.assign(data, param)
        let res = await getSegmentBindingList(data)
        if (res.IsSuccess) {
          return res.Result.CurrentPageData
        }
      } catch (err) {
        console.log(err)
      }
    },
    // 获取分割
    async getSegmentList(id) {
      try {
        let data = {
          // SegmentationId: id,
          PageSize: 9999,
          PageIndex: 1,
        }
        if (id) data.Id = id
        let res = await getSegmentList(data)
        if (res.IsSuccess) {
          return res.Result.CurrentPageData
        }
      } catch (err) {
        console.log(err)
      }
    },
    // 获取分割组
    async getSegmentationList(id) {
      try {
        let data = {
          VisitTaskId: this.visitInfo.VisitTaskId,
          PageSize: 9999,
          PageIndex: 1,
        }
        if (id) data.Id = id
        let res = await getSegmentationList(data);

        if (res.IsSuccess) {
          return res.Result.CurrentPageData;

        }
      } catch (err) {
        console.log(err)
      }
    },

    async handleViewAnnotation(obj) {
      const index = this.findMarkIndex(obj.question)
      if (index === -1) return
      const annotation = this.questionMarkInfoList[index].MeasureData
      this.$emit('viewCustomAnnotationSeries', {
        visitTaskId: this.visitTaskId,
        annotation
      })
    },
    handleRemoveAnnotation(obj) {
      const index = this.findMarkIndex(obj.question)
      if (index === -1) return
      Object.assign(this.questionMarkInfoList[index], {
        MeasureData: '',
        StudyId: '',
        SeriesId: '',
        InstanceId: '',
        OrderMarkName: '',
        PicturePath: ''
      })
      const key = this.operateRowId
        ? `${this.operateRowId}_${obj.question.Id}`
        : obj.question.Id
      this.$set(this.questionsMarkStatus, key, {
        isMarked: false,
        isSaved: false,
      })
    },
    async handleSaveNoneDicomOuterQuestions(obj) {
      this.loading = true;
      try {
        const answers = [{ QuestionId: obj.question.Id, answer: this.questionForm[obj.question.Id] }]
        const markInfo = []
        const index = this.questionMarkInfoList.findIndex(
          item => item.QuestionId === this.operateQuestionId
        )

        if (index > -1) {
          const item = { ...this.questionMarkInfoList[index] }
          item.MeasureData = item.MeasureData ? JSON.stringify(item.MeasureData) : ''
          markInfo.push(item)
          markInfo[0].PicturePath = ''
        }
        let annotation = null
        if (!this.operateRowId && obj.rowId) {
          this.operateRowId = obj.rowId
          // this.updateQuestionsMarkStatus(obj)
        }
        annotation = this.getAnnotationByRow(obj.question.Id, false)
        // 截图上传
        let picturePath = obj.picturePath
        if (annotation) {
          const base64Str = await this.getScreenshots({
            visitTaskId: this.visitTaskId,
            annotation
          })
          if (!picturePath) {
            const pictureObj = await this.uploadScreenshots(`${Date.now()}`, base64Str)
            picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
          }
          markInfo[0].PicturePath = picturePath
        }
        if (markInfo && markInfo.length > 0) {
          markInfo[0].MarkId = annotation ? annotation.annotationUID : null
        }
        await saveAnswerAndBindingNoneDicomMark({
          visitTaskId: this.visitTaskId,
          StudyId: annotation.studyId,
          NoneDicomFileId: annotation.noneDicomFileId,
          ...answers[0],
          ...markInfo[0]
        })
        this.loading = false
        this.$set(this.questionsMarkStatus, obj.question.Id, {
          isMarked: !!this.questionMarkInfoList[index]?.MeasureData,
          isSaved: true,
          OrderMarkName: index > -1 ? this.questionMarkInfoList[index].OrderMarkName : ''
        })
        this.resetOperateState()
        if (annotation) {
          for (let i = 0; i < this.questionMarkInfoList.length; i++) {
            const item = this.questionMarkInfoList[i]
            if (!item.MeasureData || item.MeasureData.annotationUID !== annotation.annotationUID) continue
            const isTableMode = item.TableQuestionId
            if (!isTableMode && this.questionsMarkStatus[item.QuestionId] && !this.questionsMarkStatus[item.QuestionId].isSaved && this.questionsMarkStatus[item.QuestionId].isMarked) {
              DicomEvent.$emit('operateImageMarker', { QuestionId: item.QuestionId, operateStateEnum: 5, picturePath })
              break
            }
          }
        }
      } catch (err) {
        console.log(err)
        this.loading = false
      }
    },
    async handleSaveOuterQuestions(obj) {
      this.loading = true;
      try {
        const answers = [{ id: obj.question.Id, answer: this.questionForm[obj.question.Id] }]
        const markInfo = []
        const index = this.questionMarkInfoList.findIndex(
          item => item.QuestionId === this.operateQuestionId
        )

        if (index > -1) {
          const item = { ...this.questionMarkInfoList[index] }
          item.MeasureData = item.MeasureData ? JSON.stringify(item.MeasureData) : ''
          markInfo.push(item)
        }
        let annotation = null
        if (!this.operateRowId && obj.rowId) {
          this.operateRowId = obj.rowId
          // this.updateQuestionsMarkStatus(obj)
        }
        annotation = this.getAnnotationByRow(obj.question.Id, false)
        // 截图上传
        let picturePath = obj.picturePath
        if (annotation) {
          const base64Str = await this.getScreenshots({
            visitTaskId: this.visitTaskId,
            annotation
          })
          if (!picturePath) {
            const pictureObj = await this.uploadScreenshots(`${Date.now()}`, base64Str)
            picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
          }
          markInfo[0].PicturePath = picturePath
        }
        if (markInfo && markInfo.length > 0) {
          markInfo[0].MarkId = annotation ? annotation.annotationUID : null
        }
        await saveTaskQuestion(-10, {
          visitTaskId: this.visitTaskId,
          answers,
          questionMarkInfoList: markInfo
        })
        this.$set(this.questionsMarkStatus, obj.question.Id, {
          isMarked: !!this.questionMarkInfoList[index]?.MeasureData,
          isSaved: true,
          OrderMarkName: index > -1 ? this.questionMarkInfoList[index].OrderMarkName : ''
        })
        this.resetOperateState()
        if (annotation) {
          for (let i = 0; i < this.questionMarkInfoList.length; i++) {
            const item = this.questionMarkInfoList[i]
            if (!item.MeasureData || item.MeasureData.annotationUID !== annotation.annotationUID) continue
            const isTableMode = item.TableQuestionId
            if (!isTableMode && this.questionsMarkStatus[item.QuestionId] && !this.questionsMarkStatus[item.QuestionId].isSaved && this.questionsMarkStatus[item.QuestionId].isMarked) {
              DicomEvent.$emit('operateImageMarker', { QuestionId: item.QuestionId, operateStateEnum: 5, picturePath, visitTaskId: this.visitTaskId })
              break
            }
          }
        }
      } catch (e) {
        console.error('保存失败:', e)
      } finally {
        this.loading = false
      }
    },
    handleUpdateValue(obj) {
      const key = this.operateRowId
        ? `${this.operateRowId}_${obj.question.Id}`
        : obj.question.Id
      this.$set(this.questionsMarkStatus, key, {
        isMarked: false,
        isSaved: false,
      })
    },
    async handleSaveNoneDicomTableQuestions(obj) {
      const loading = this.$loading({ fullscreen: true })
      try {
        let annotation = null
        if (!this.operateRowId && obj.rowId && obj.question.ParentQsId) {
          this.operateRowId = obj.rowId
          this.updateQuestionsMarkStatus(obj)
        }
        annotation = this.getAnnotationByRow(this.operateRowId)
        // 截图上传
        let picturePath = obj.picturePath
        if (annotation && !picturePath) {
          const base64Str = await this.getScreenshots({
            visitTaskId: this.visitTaskId,
            annotation
          })
          const pictureObj = await this.uploadScreenshots(`${Date.now()}`, base64Str)
          picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
        }
        await saveAnswerAndBindingNoneDicomMark({
          Answer: obj.answer,
          VisitTaskId: this.visitTaskId,
          QuestionId: obj.question.ParentQsId,
          ...(annotation ? {
            StudyId: annotation.studyId,
            MarkTool: annotation.markTool || '',
            MeasureData: JSON.stringify(annotation),
            OrderMarkName: annotation.data.label || '',
            NoneDicomFileId: annotation.noneDicomFileId,
          } : {
            MarkTool: '',
            OrderMarkName: ''
          }),
          Path: annotation.path || '',
          PicturePath: picturePath ? picturePath : '',
          QuestionType: 0,
          RowId: this.operateRowId,
          TableQuestionId: this.operateQuestionId,
          RowIndex: obj.rowIndex,
          MarkId: annotation ? annotation.annotationUID : null
        })
        this.$set(this.questionsMarkStatus,
          `${this.operateRowId}_${this.operateQuestionId}`,
          { isMarked: !!annotation, isSaved: true, OrderMarkName: annotation ? annotation.data.label : '' }
        )
        this.resetOperateState()
        if (annotation) {
          for (let i = 0; i < this.questionMarkInfoList.length; i++) {
            const item = this.questionMarkInfoList[i]
            if (!item.MeasureData || item.MeasureData.annotationUID !== annotation.annotationUID) continue
            const isTableMode = item.TableQuestionId
            if (isTableMode && ((this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`] && !this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`].isSaved && this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`].isMarked) || (this.questionsMarkStatus[`${item.TableQuestionId}`] && !this.questionsMarkStatus[`${item.TableQuestionId}`].isSaved && this.questionsMarkStatus[`${item.TableQuestionId}`].isMarked))) {
              DicomEvent.$emit('operateImageMarkerTable', { QuestionId: item.TableQuestionId, operateStateEnum: 7, picturePath })
              break
            }
          }
        }
      } catch (e) {
        console.error('表格保存失败:', e)
      } finally {
        loading.close()
      }
    },
    async handleSaveTableQuestions(obj) {
      const loading = this.$loading({ fullscreen: true })
      try {
        let annotation = null
        if (!this.operateRowId && obj.rowId && obj.question.ParentQsId) {
          this.operateRowId = obj.rowId
          this.updateQuestionsMarkStatus(obj)
        }
        annotation = this.getAnnotationByRow(this.operateRowId)
        // 截图上传
        let picturePath = obj.picturePath
        if (annotation && !picturePath) {
          const base64Str = await this.getScreenshots({
            visitTaskId: this.visitTaskId,
            annotation
          })
          const pictureObj = await this.uploadScreenshots(`${Date.now()}`, base64Str)
          picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
        }
        await saveTableQuestionMark({
          Answer: obj.answer,
          VisitTaskId: this.visitTaskId,
          QuestionId: obj.question.ParentQsId,
          ...(annotation ? {
            InstanceId: annotation.instanceId,
            SeriesId: annotation.seriesId,
            StudyId: annotation.studyId,
            MarkTool: annotation.markTool,
            NumberOfFrames: annotation.numberOfFrames,
            MeasureData: JSON.stringify(annotation),
            OrderMarkName: annotation.data.label
          } : {}),
          PicturePath: picturePath,
          QuestionType: 0,
          RowId: this.operateRowId,
          TableQuestionId: this.operateQuestionId,
          RowIndex: obj.rowIndex,
          MarkId: annotation ? annotation.annotationUID : null
        }, -10)
        this.$set(this.questionsMarkStatus,
          `${this.operateRowId}_${this.operateQuestionId}`,
          { isMarked: !!annotation, isSaved: true, OrderMarkName: annotation ? annotation.data.label : '' }
        )
        this.resetOperateState()
        if (annotation) {
          for (let i = 0; i < this.questionMarkInfoList.length; i++) {
            const item = this.questionMarkInfoList[i]
            if (!item.MeasureData || item.MeasureData.annotationUID !== annotation.annotationUID) continue
            const isTableMode = item.TableQuestionId
            if (isTableMode && ((this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`] && !this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`].isSaved && this.questionsMarkStatus[`${item.RowId}_${item.TableQuestionId}`].isMarked) || (this.questionsMarkStatus[`${item.TableQuestionId}`] && !this.questionsMarkStatus[`${item.TableQuestionId}`].isSaved && this.questionsMarkStatus[`${item.TableQuestionId}`].isMarked))) {
              DicomEvent.$emit('operateImageMarkerTable', { QuestionId: item.TableQuestionId, operateStateEnum: 7, picturePath })
              break
            }
          }
        }
      } catch (e) {
        console.error('表格保存失败:', e)
      } finally {
        loading.close()
      }
    },
    verifyAnnotationIsSave() {
      return Object.keys(this.questionsMarkStatus).some(key => !this.questionsMarkStatus[key].isSaved)
    },
    removeAllNoSaveAnnotation() {
      Object.keys(this.questionsMarkStatus).forEach(key => {
        if (!this.questionsMarkStatus[key].isSaved) {
          if (key.includes("_")) {
            let QuestionId = key.split("_")[1]
            DicomEvent.$emit('operateImageMarkerTable', { QuestionId, operateStateEnum: 4 })
          } else {
            let QuestionId = key
            let res = this.findQuestion(QuestionId, this.questions)
            if (res) {
              DicomEvent.$emit('operateImageMarker', { QuestionId, operateStateEnum: 4 })
            } else {
              DicomEvent.$emit('operateImageMarkerTable', { QuestionId, operateStateEnum: 4 })
            }
          }
        }
      })
    },
    findQuestion(id, arr) {
      for (let i = 0; i < arr.length; i++) {
        let item = arr[i]
        if (item.Id === id) return true
        if (item.Childrens) {
          let res = this.findQuestion(id, item.Childrens)
          if (res) return true
        }
        if (i === arr.length - 1) return false
      }
    },
    findMarkIndex(question) {
      const { Id, RowId } = question
      if (this.isTableQuestion) {
        return RowId
          ? this.questionMarkInfoList.findIndex(i =>
            i.TableQuestionId === Id && i.RowId === RowId)
          : this.questionMarkInfoList.findIndex(i =>
            i.TableQuestionId === Id && !i.RowId)
      }
      return this.questionMarkInfoList.findIndex(i => i.QuestionId === Id)
    },
    updateQuestionsMarkStatus(obj) {
      this.questionMarkInfoList.forEach(item => {
        if (item.QuestionId === obj.question.ParentQsId && !item.RowId) {
          item.RowId = obj.rowId
          const oldKey = item.TableQuestionId
          const newKey = `${obj.rowId}_${item.TableQuestionId}`

          if (this.questionsMarkStatus[oldKey]) {
            const status = { ...this.questionsMarkStatus[oldKey] }
            delete this.questionsMarkStatus[oldKey]
            this.$set(this.questionsMarkStatus, newKey, status)
          }
        }
      })
    },
    getAnnotationByRow(rowId, isTable = true) {
      let index = -1;
      if (isTable) {
        index = this.questionMarkInfoList.findIndex(
          i => i.RowId === rowId && i.TableQuestionId === this.operateQuestionId
        )
      } else {
        index = this.questionMarkInfoList.findIndex(
          i => i.QuestionId === rowId
        )
      }
      return index > -1 ? this.questionMarkInfoList[index].MeasureData : null
    },
    async bindAnnotationToQuestion(annotation) {
      try {
        const VALID_STATES = [null, 0, 1, 3]
        const currentState = this.operateStateEnum
        if (!VALID_STATES.includes(currentState)) return
        const isInvalidAnnotation = currentState === 1 && annotation.markTool !== this.imageTool
        if (isInvalidAnnotation) return
        if (currentState === null) {
          return this.handleNullState(annotation)
        }
        if (!this.operateQuestionId) return
        if ([0, 1, 3].includes(currentState)) {
          // 该标记不能与问题绑定！
          if (!annotation.data.label || annotation.markTool !== this.imageTool) {
            let message = this.$t("dicom3D:CustomizeQuestionList:alert:markNoSaveToQuestion").replace("xxx", this.$t(`dicom3D:mark:${this.imageTool}`))
            this.$alert(message)
            return
          }
          // if (currentState === 3) {
          let conflictIndex = this.questionMarkInfoList.findIndex(
            item => item.MeasureData.annotationUID === annotation.annotationUID
              && item.RowId !== this.operateRowId && item.RowId
          )
          // && this.operateRowId
          if (conflictIndex > -1) {
            //该标记已绑定到其他行，不能更改绑定！
            this.$alert(this.$t("dicom3D:CustomizeQuestionList:alert:markIsbind"))
            return
          }
          conflictIndex = this.questionMarkInfoList.findIndex(
            item => item.MeasureData.annotationUID === annotation.annotationUID
              && !item.TableQuestionId && this.isTableQuestion
          )
          if (conflictIndex > -1) {
            //该标记已绑定到外层问题，不能更改绑定！
            this.$alert(this.$t("dicom3D:CustomizeQuestionList:alert:markIsbind2"))
            return
          }
          // }
          // 是否确认绑定？ 是否确认更改？
          let message = currentState === 0 ? this.$t("dicom3D:CustomizeQuestionList:confirm:bindYesOrNo") : currentState === 3 ? this.$t("dicom3D:CustomizeQuestionList:confirm:updateYesOrNo") : null
          if (message) {
            message = message.replace('xxx', this.operateQuestionName).replace('yyy', annotation.data.label)
            const result = await this.$confirm(message, {
              type: 'warning',
              distinguishCancelAndClose: true
            })
            const isConfirmed = result === 'confirm'
            if (!isConfirmed) return
          }
        }
        const targetIndex = this.findTargetIndex()
        if (targetIndex === -1) {
          this.questionMarkInfoList.push({
            InstanceId: annotation.instanceId,
            SeriesId: annotation.seriesId,
            OrderMarkName: annotation.data.label,
            StudyId: annotation.studyId,
            MarkTool: annotation.metadata.toolName,
            PicturePath: '',
            Path: annotation.path,
            NumberOfFrames: annotation.numberOfFrames,
            MeasureData: annotation,
            RowId: this.operateRowId || '',
            QuestionId: this.isTableQuestion
              ? this.operateParentQsId
              : this.operateQuestionId,
            TableQuestionId: this.isTableQuestion
              ? this.operateQuestionId
              : ''
          })
        } else {
          const target = this.questionMarkInfoList[targetIndex]
          Object.assign(target, {
            InstanceId: annotation.instanceId,
            SeriesId: annotation.seriesId,
            StudyId: annotation.studyId,
            OrderMarkName: annotation.data.label,
            MarkTool: annotation.metadata.toolName,
            PicturePath: '',
            NumberOfFrames: annotation.numberOfFrames,
            MeasureData: annotation
          })
        }
        this.updateMarkStatus(targetIndex, annotation)
        this.operateStateEnum = null
      } catch (e) {
        console.error('绑定失败:', e); // 增强错误信息
      }
    },
    handleNullState(annotation) {
      const qsArr = []
      const markList = this.questionMarkInfoList
      for (let i = 0; i < markList.length; i++) {
        const item = markList[i];
        if (item.MeasureData?.annotationUID !== annotation.annotationUID) continue
        item.MeasureData = annotation

        if (item.TableQuestionId) {
          qsArr.push({ ...item, ImageToolAttribute: this.imageToolAttribute })

          const keyId = item.RowId
            ? `${item.RowId}_${item.TableQuestionId}`
            : item.TableQuestionId

          this.$set(this.questionsMarkStatus, keyId, {
            isMarked: true,
            isSaved: false,
          })
        } else {
          this.setAnswerToQuestion(annotation, item.QuestionId)
          this.$set(this.questionsMarkStatus, item.QuestionId, {
            isMarked: true,
            isSaved: false,
          })
        }
      }
      if (qsArr.length) {
        store.dispatch('dicom3d/setOperateInfo', qsArr)
      }
    },
    findTargetIndex() {
      if (this.isTableQuestion && this.operateRowId) {
        return this.questionMarkInfoList.findIndex(
          item => item.TableQuestionId === this.operateQuestionId
            && item.RowId === this.operateRowId
        )
      } else if (this.isTableQuestion) {
        return this.questionMarkInfoList.findIndex(
          item => item.TableQuestionId === this.operateQuestionId
            && !item.RowId
        )
      }
      return this.questionMarkInfoList.findIndex(
        item => item.QuestionId === this.operateQuestionId
      )
    },

    updateMarkStatus(index, annotation) {
      const status = { isMarked: true, isSaved: false }
      if (this.isTableQuestion) {
        const keyId = index > -1 && this.questionMarkInfoList[index].RowId
          ? `${this.questionMarkInfoList[index].RowId}_${this.questionMarkInfoList[index].TableQuestionId}`
          : this.operateRowId
            ? `${this.operateRowId}_${this.operateQuestionId}`
            : this.operateQuestionId

        this.$set(this.questionsMarkStatus, keyId, status)
        store.dispatch('dicom3d/setOperateInfo', [{
          MeasureData: annotation,
          QuestionId: this.operateParentQsId,
          TableQuestionId: this.operateQuestionId,
          RowId: this.operateRowId,
          ImageToolAttribute: this.imageToolAttribute
        }])
      } else {
        this.setAnswerToQuestion(annotation, this.operateQuestionId)
        this.$set(this.questionsMarkStatus, this.operateQuestionId, status)
      }
    },

    updateAnnotationToQuestion(annotation) {
      const questionMarkInfo = { isMarked: true, isSaved: false }
      const qsArr = []
      for (let i = 0; i < this.questionMarkInfoList.length; i++) {
        const item = this.questionMarkInfoList[i]
        if (!item.MeasureData || item.MeasureData.annotationUID !== annotation.annotationUID) continue
        item.MeasureData = annotation
        const isTableMode = this.isTableQuestion || item.TableQuestionId
        if (!isTableMode) {
          this.imageToolAttribute = null
          this.setAnswerToQuestion(annotation, item.QuestionId)
          this.$set(this.questionsMarkStatus, item.QuestionId, questionMarkInfo)
          continue
        }
        this.operateParentQsId = item.QuestionId
        this.operateQuestionId = item.TableQuestionId
        this.operateRowId ||= item.RowId
        qsArr.push({ ...item })
        const keyId = item.RowId ? `${item.RowId}_${item.TableQuestionId}` : item.TableQuestionId;
        this.$set(this.questionsMarkStatus, keyId, questionMarkInfo);
        if (item.RowId) {
          DicomEvent.$emit('openAddTableCol', { RowId: item.RowId })
        }
      }
      if (qsArr.length > 0) {
        store.dispatch('dicom3d/setOperateInfo', qsArr);
      }
    },
    setAnswerToQuestion(annotation, questionId) {
      if (!questionId || !annotation) return
      let prop = ''
      if (!this.imageToolAttribute) {
        prop = this.questionImageToolAttributeInfo[questionId]
      } else {
        prop = this.imageToolAttribute
      }
      let val = this.getAnnotationProp(annotation, prop)
      this.$set(this.questionForm, questionId, val)
      this.classArr.map(i => {
        if (i.triggerId === questionId) {
          let answer = null
          const list = JSON.parse(i.classifyAlgorithms)
          if (i.classifyType === 0) {
            const o = list.find(v => {
              return (
                parseFloat(val) >= parseFloat(v.gt) &&
                parseFloat(val) < parseFloat(v.lt)
              )
            })
            answer = o ? o.label : 'NE'
          } else if (i.classifyType === 1) {
            const o = list.find(v => {
              return v.val.includes(val)
            })
            answer = o ? o.label : null
          }
          this.$set(this.questionForm, i.classId, answer)
        }
      })
    },
    getAnnotationProp(annotation, prop) {
      if (!annotation || !prop) return
      let referencedImageId = null
      if (annotation.from || annotation.metadata.volumeId) {
        referencedImageId = `${annotation?.metadata?.volumeId}?sliceIndex=${annotation?.metadata?.sliceIndex}&viewPlaneNormal=${annotation?.metadata?.viewPlaneNormal.map(i => i == 0 ? Number(0).toFixed(3) : Number(i).toFixed(3)).join(',')}`
      } else {
        referencedImageId = annotation?.metadata?.referencedImageId
      }
      if (!referencedImageId) return null
      const cacheKey = annotation.from || annotation.metadata.volumeId ? `volumeId:${referencedImageId}` : `imageId:${referencedImageId}`
      const points = ['x', 'y', 'z']
      const cachedStats = annotation.markTool === "ArrowAnnotate"
        ? annotation.data?.handles?.points[0]
        : this.getAnnotationCachedStats(annotation, cacheKey, prop)
      const hasProp = cachedStats
        && (Object.prototype.hasOwnProperty.call(cachedStats, prop) || cachedStats[points.indexOf(prop)])
      if (!hasProp) return null
      let value = annotation.markTool === "ArrowAnnotate" ? cachedStats[points.indexOf(prop)] : cachedStats[prop]
      if (this.isNoneDicom && annotation.ps && value !== null) {
        let ps = annotation.ps
        if (prop === 'area') {
          value = this.reRound(csUtils.roundNumber(value * ps * ps), this.digitPlaces)
        } else if (prop === 'length' || prop === 'perimeter' || prop === 'width') {
          value = this.reRound(csUtils.roundNumber(value * ps), this.digitPlaces)
        } else {
          value = this.reRound(csUtils.roundNumber(value), this.digitPlaces)
        }
      } else if (this.isNoneDicom && value !== null) {
        value = this.reRound(csUtils.roundNumber(value), this.digitPlaces)
      }
      if (prop === 'total' && value !== null) {
        return this.formatStatSum(value)
      }
      return value !== null
        ? parseFloat(value).toFixed(this.digitPlaces)
        : value
    },
    getAnnotationCachedStats(annotation, cacheKey, prop) {
      const cachedStatsMap = annotation?.data?.cachedStats || {}
      const matchedStats = cachedStatsMap[cacheKey]
      if (prop !== 'total') return matchedStats
      const nmStats = Object.values(cachedStatsMap).find(item => item?.Modality === 'NM' && item.total !== undefined && item.total !== null)
      return nmStats || matchedStats
    },
    formatStatSum(value) {
      const num = Number(value)
      if (!Number.isFinite(num)) return value

      if (Math.abs(num - Math.round(num)) < 1e-6) {
        return String(Math.round(num))
      }

      return this.reRound(num, this.digitPlaces)
    },
    reRound(result, finalPrecision) {
      if (typeof result === 'string' && result.includes(', ')) {
        const numStrs = result.split(', ')
        const processed = numStrs.map(str => this.processSingle(str, finalPrecision))
        return processed.join(', ')
      }
      return this.processSingle(result, finalPrecision)
    },
    processSingle(str, precision) {
      const num = parseFloat(str)
      if (isNaN(num)) return 'NaN'

      // 保留原极小值处理逻辑
      if (Math.abs(num) < 0.0001) return str
      const factor = 10 ** precision
      return (Math.round(num * factor + 0.0000001) / factor).toFixed(precision)
    },
    unBindAnnotationToQuestion(obj) {
      const { markTableQuestions = [], questionId } = obj || {}
      const { questionMarkInfoList, questionsMarkStatus } = this
      if (!Array.isArray(markTableQuestions) || !questionId || !Array.isArray(questionMarkInfoList)) {
        return
      }
      this.questionMarkInfoList = questionMarkInfoList.filter(item => {
        const { TableQuestionId, QuestionId, RowId } = item || {}
        if ((TableQuestionId && QuestionId === questionId && markTableQuestions.includes(TableQuestionId)) && !RowId) {
          if (questionsMarkStatus && questionsMarkStatus[TableQuestionId]) {
            delete questionsMarkStatus[TableQuestionId]
          } else {
            return item
          }
        } else {
          return item
        }
      })
    },
    // 获取截图
    getScreenshots(obj) {
      return new Promise((resolve, reject) => {
        this.$emit('getCustomScreenshots', obj, resolve) // 将resolve传递给父组件
      })
    },
    async uploadScreenshots(fileName, file) {
      try {
        file = this.convertBase64ToBlob(file)
        const trialId = this.$route.query.trialId
        const taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
        const subjectId = taskInfo.SubjectId
        const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
        return { isSuccess: true, result: result }
      } catch (e) {
        console.log(e)
        return { isSuccess: false, result: e }
      }
    },
    convertBase64ToBlob(imageEditorBase64) {
      const base64Arr = imageEditorBase64.split(',')
      let imgtype = ''
      let base64String = ''
      if (base64Arr.length > 1) {
        base64String = base64Arr[1]
        imgtype = base64Arr[0].substring(
          base64Arr[0].indexOf(':') + 1,
          base64Arr[0].indexOf(';')
        )
      }
      const bytes = atob(base64String)
      const bytesCode = new ArrayBuffer(bytes.length)
      const byteArray = new Uint8Array(bytesCode)
      for (let i = 0; i < bytes.length; i++) {
        byteArray[i] = bytes.charCodeAt(i)
      }
      return new Blob([bytesCode], { type: imgtype })
    },
    resetOperateState() {
      console.log('resetOperateState')
      this.operateStateEnum = null
      this.operateQuestionId = ''
      this.operateRowId = ''
      this.imageTool = ''
      this.imageToolAttribute = ''
    },
    async resetForm() {
      const confirm = await this.$confirm(
        this.$t('trials:dicomReading:message:confirmReset1'),
        this.$t('trials:dicomReading:message:confirmReset2'),
        {
          type: 'warning',
          distinguishCancelAndClose: true
        }
      )
      if (confirm !== 'confirm') return
      this.$emit('setReadingToolPassive')
      const loading = this.$loading({ fullscreen: true })
      try {
        const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
        if (res.IsSuccess) {
          this.rerender = false
          await this.getQuestionCalculateRelation()
          await this.getQuestions(true)
          this.$emit('resetAnnotations', this.visitTaskId)
          this.initSegmentBinding()
          this.$nextTick(() => {
            this.rerender = true
          })
        }
        loading.close()
      } catch (e) {
        loading.close()
        console.log(e)
      }
    },
    receiveMsg(event) {
      if (event.data.type === 'isCanActiveNoneDicomTool') {
        let obj = { isCanActiveTool: true, lesionName: '', reason: '', toolName: event.data.toolName }
        DicomEvent.$emit('isCanActiveNoneDicomTool', obj)
      } else if (event.data.type === 'setMeasurement') {
        // this.setMeasuredData(event.data.data)
      }
    },
    async changePlottingScaleChangeAnswer(data) {
      try {
        let { noneDicomFileId, path, picturePath, isRemovePlottingScale, psArr } = data
        let param = {
          VisitTaskId: this.visitTaskId,
          NoneDicomFileId: noneDicomFileId,
          Path: path,
          PicturePath: picturePath,
          IsRemovePlottingScale: isRemovePlottingScale,
          AnswerList: []
        }
        if (!isRemovePlottingScale) {
          this.questionMarkInfoList.forEach(item => {
            DicomEvent.$emit('closeAddTableCol', { RowId: item.RowId })
            let prop = this.questionImageToolAttributeInfo[item.QuestionId] || this.questionImageToolAttributeInfo[item.TableQuestionId]
            if (item.Path === path && ['length', 'perimeter', 'area', 'width'].includes(prop)) {
              const referencedImageId = item?.MeasureData?.metadata?.referencedImageId
              if (!referencedImageId) return null
              const cacheKey = `imageId:${referencedImageId}`
              const cachedStats = item?.MeasureData.data?.cachedStats?.[cacheKey]
              const hasProp = cachedStats
                && Object.prototype.hasOwnProperty.call(cachedStats, prop)
              if (!hasProp) return null
              let value = cachedStats[prop]
              let ps = null
              const i = psArr.findIndex(i => i.Path === path)
              if (i > -1 && psArr[i].PS) {
                ps = parseFloat(psArr[i].PS).toFixed(3)
              }
              if (ps) {
                if (prop === 'area') value = this.reRound(csUtils.roundNumber(value * ps * ps), this.digitPlaces)
                if (prop === 'length' || prop === 'perimeter' || prop === 'width') value = this.reRound(csUtils.roundNumber(value * ps), this.digitPlaces)
              } else {
                value = this.reRound(csUtils.roundNumber(value), this.digitPlaces)
              }
              let obj = {
                QuestionId: item.QuestionId,
                RowId: item.RowId,
                TableQuestionId: item.TableQuestionId,
                Answer: value
              }
              param.AnswerList.push(obj)
            }
          })
        }
        this.loading = true
        let res = await changePlottingScaleChangeAnswer(param)
        this.loading = false
        if (res.IsSuccess) {
          this.getQuestions()
        }
      } catch (err) {
        console.log(err)
      }
    },
    openFeedBackTable() {
      this.$FB({
        type: 'imgfail',
        trialId: this.$route.query.trialId,
        visitTaskId: this.visitTaskId,
        callBack: async () => {
          try {
            await this.$confirm(
              this.$t('trials:reading:confirm:feedbackmsg'),
              {
                type: 'warning',
                distinguishCancelAndClose: true
              }
            ).catch(() => {})
            this.loading = true
            const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
            this.loading = false
            if (res.IsSuccess) {
              window.location.reload()
            }
          } catch (err) {
            this.loading = false
          }
        }
      })
    }
  },
  watch: {
    questionsMarkStatus: {
      handler() {
        let saved = true
        Object.keys(this.questionsMarkStatus).forEach(key => {
          if (!this.questionsMarkStatus[key].isSaved) saved = false
        })
        this.$emit('setSaved', saved)
      },
      deep: true,
      immediate: true
    },
    questionForm: {
      handler() {
        this.isSaved = false
      },
      deep: true
    }
    // questionMarkInfoList: {
    //   handler() {
    //     console.log(this.questionMarkInfoList, 'questionMarkInfoList')
    //   },
    //   deep: true,
    //   immediate: true
    // }
  }
}
</script>
<style lang="scss" scoped>
.questionList-wrapper {
  height: 100%;
  overflow-y: auto;

  .container {
    padding: 10px;

    .basic-info {
      display: flex;
      justify-content: space-between;
      align-items: center;

      h3 {
        color: #ddd;
        padding: 5px 0px;
        margin: 0;
      }

      i {
        color: #fff;
        font-size: 22px;
        font-weight: bold;
        cursor: pointer;
      }
    }

    .ecrf-form {
      ::v-deep .el-form-item__label {
        color: #ddd;
      }
    }

    ::v-deep .el-table,
    .el-table__expanded-cell {
      background-color: #000;
      color: #fff;
      border-color: #444444;
    }

    ::v-deep .el-table th,
    .el-table tr {
      background-color: #000;
      color: #fff;
      border-color: #444444;
    }

    ::v-deep .el-table__body tr>td {
      background-color: #000 !important;
      color: #fff;
      border-color: #444444;
    }

    ::v-deep .el-table__body tr:hover>td {
      background-color: #858282 !important;
      color: #fff;
      border-color: #444444;
    }

    ::v-deep .el-table--border th.gutter:last-of-type {
      border: none;
    }

    ::v-deep .el-dialog {
      background: #1e1e1e;
      border: 1px solid #ddd;
      color: #ddd;

      .el-dialog__title {
        color: #fff;
      }

      .el-input .el-input__inner {
        background-color: transparent;
        color: #ddd;
        border: 1px solid #5e5e5e;
      }

      .el-input.is-disabled .el-input__inner {
        background-color: #646464a1;
      }

      .el-form-item__label {
        color: #dfdfdf
      }
    }
  }
  .action-bar {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
  }
  .feedback-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-weight: 400;
    font-size: 24px;
    line-height: 1;
    cursor: pointer;

    &:hover {
      color: #68a2d5;
    }
  }
}

// .ecrf-list-container{
//   min-height:400px;
//   color: #ddd;

// }
</style>
