<template>
  <div ref="dicom-wrapper" class="dicom-wrapper">
    <div ref="dicomViewer" class="dicom-viewer">
      <!-- <div v-for="i in layoutRow" :key="i" class="dicom-row" :style="{height: rowHeight}">
        <div v-for="j in layoutCol" :key="j" class="dicom-item" oncontextmenu="return false">
          <dicom-canvas  :isComparison="isComparison" ref="dicomCanvas" style="width:100%;height:100%" />
        </div>
      </div>-->
      <div class="Anonymous" v-if="isAnonymous">
        <div
          :class="{ btn: true, activeBtn: activeTool === 'Note_RectangleRoi' && !isComparison, isNoted: isComparison }"
          @click="setToolActive($event, 'Note_RectangleRoi', true)">{{
            $t('DicomViewer:anonymous:Note_RectangleRoi') }}</div>
        <div :class="{ btn: true, activeBtn: activeTool === 'Eraser' && !isComparison, isNoted: isComparison }"
          @click="setToolActive($event, 'Eraser', true)">{{
            $t('DicomViewer:anonymous:Eraser') }}
        </div>
        <div :class="{ btn: true, isNoted: isComparison }" @click="anonymousImage(false)">{{
          $t('DicomViewer:anonymous:Application') }}</div>
        <div :class="{ btn: true, isNoted: isComparison }" v-if="!isMultiple" @click="anonymousImage(true)">{{
          $t('DicomViewer:anonymous:ApplicationAll') }}</div>
        <!-- <div class="btn">刷新图像</div> -->
        <div class="btn" v-if="!isComparison" @click="comparison(true)">{{
          $t('DicomViewer:anonymous:Comparison') }}</div>
        <div class="btn" v-else @click="comparison(false)">{{
          $t('DicomViewer:anonymous:Exit') }}</div>
        <div :class="{ btn: true }" @click="recovery(false)">{{
          $t('DicomViewer:anonymous:Recovery') }}</div>
        <div :class="{ btn: true }" @click="recovery(true)">{{
          $t('DicomViewer:anonymous:RecoveryAll') }}</div>
      </div>
      <div v-show="layoutRow >= 1" class="dicom-row" :style="{ height: rowHeight }">
        <div v-show="layoutRow >= 1 && layoutCol >= 1" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas0' }" data-index="0" @click="activateDicomCanvas(0)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas0" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow >= 1 && layoutCol >= 2" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas1' }" data-index="1" @click="activateDicomCanvas(1)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas1" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow >= 1 && layoutCol >= 3" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas2' }" data-index="2" @click="activateDicomCanvas(2)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas2" style="width:100%;height:100%" />
        </div>
      </div>

      <div v-show="layoutRow >= 2" class="dicom-row" :style="{ height: rowHeight }">
        <div v-show="layoutRow >= 2 && layoutCol >= 1" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas3' }" data-index="3" @click="activateDicomCanvas(3)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas3" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow >= 2 && layoutCol >= 2" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas4' }" data-index="4" @click="activateDicomCanvas(4)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas4" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow >= 2 && layoutCol >= 3" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas5' }" data-index="5" @click="activateDicomCanvas(5)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas5" style="width:100%;height:100%" />
        </div>
      </div>

      <div v-show="layoutRow == 3" class="dicom-row" :style="{ height: rowHeight }">
        <div v-show="layoutRow == 3 && layoutCol >= 1" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas6' }" data-index="6" @click="activateDicomCanvas(6)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas6" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow == 3 && layoutCol >= 2" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas7' }" data-index="7" @click="activateDicomCanvas(7)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas7" style="width:100%;height:100%" />
        </div>
        <div v-show="layoutRow == 3 && layoutCol >= 3" class="dicom-item"
          :class="{ 'activeItem': activeItem == 'dicomCanvas8' }" data-index="8" @click="activateDicomCanvas(8)"
          @dblclick="setFullScreen($event)">
          <dicom-canvas :isComparison="isComparison" ref="dicomCanvas8" style="width:100%;height:100%" />
        </div>
      </div>
    </div>

    <div ref="dicomTools" class="dicom-tools">
      <!-- 布局 -->
      <div class="measureTool-wrapper">
        <div class="sideTool-title">{{ $t('trials:reading:button:layout') }}</div>
        <div class="sideTool-wrapper">
          <label>{{ $t('trials:reading:button:layout') }}:</label>
          <select class="sidetool-select" style="width:90px" :disabled="isAnonymous" @change="changeLayout($event)">
            <option value="1x1" selected>1x1</option>
            <option value="1x2">1x2</option>
            <option value="2x1">2x1</option>
            <option value="2x2">2x2</option>
            <option value="1x3">1x3</option>
            <option value="3x1">3x1</option>
            <option value="2x3">2x3</option>
            <option value="3x2">3x2</option>
            <option value="3x3">3x3</option>
          </select>
          <div :class="{ btnBox: true, activeBtnBox: isAnonymous }" v-if="hasAnonymous && hasPermi(['role:iqc'])"
            @click="openAnonymous">{{
              $t('DicomViewer:anonymous:PixelAnonymity')
            }}
          </div>
        </div>
      </div>
      <!-- 图像变换 -->
      <div class="measureTool-wrapper">
        <div class="sideTool-title">{{ $t('trials:dicom-show:transform') }}</div>
        <div class="sideTool-wrapper">
          <button :title="$t('trials:reading:button:wwwc')" class="btn-link" data-tool="Wwwc"
            @click="setToolActive($event, 'Wwwc')">
            <svg-icon icon-class="reverse" style="font-size:20px;" />
          </button>
          <!-- <button
            title="区域调窗"
            class="btn-link"
            data-tool="WwwcRegion"
            @click="setToolActive($event,'WwwcRegion')"
          >
            <svg-icon icon-class="wwwcRegion" style="font-size:20px;" />
          </button>-->
          <button :title="$t('trials:reading:button:reverseColor')" class="btn-link" @click="toggleInvert">
            <svg-icon icon-class="reversecolor" style="font-size:20px;" />
          </button>
          <button :title="$t('trials:reading:button:zoom')" class="btn-link" data-tool="Zoom"
            @click="setToolActive($event, 'Zoom')">
            <svg-icon icon-class="magnifier" style="font-size:20px;" />
          </button>
          <button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify"
            @click="setToolActive($event, 'Magnify')">
            <svg-icon icon-class="zoom" style="font-size:20px;" />
          </button>
          <button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
            <svg-icon icon-class="rotate" style="font-size:20px;" />
            <div class="dropdown-content">
              <div @click.stop="setDicomCanvasRotate(1)">{{ $t('trials:reading:button:rotateDefault') }}</div>
              <div @click.stop="setDicomCanvasRotate(2)">{{ $t('trials:reading:button:rotateHorizontal') }}</div>
              <div @click.stop="setDicomCanvasRotate(3)">{{ $t('trials:reading:button:rotateVertical') }}</div>
              <div @click.stop="setDicomCanvasRotate(4)">{{ $t('trials:reading:button:rotateTurnLeft') }}</div>
              <div @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</div>
            </div>
          </button>
          <button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan"
            @click="setToolActive($event, 'Pan')">
            <svg-icon icon-class="move" style="font-size:20px;" />
          </button>
          <button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow"
            @click="fitToType($event, 'fitToWindow')">
            <svg-icon icon-class="fitToWindow" style="font-size:20px;" />
          </button>
          <button :title="$t('trials:reading:button:fitImage')" class="btn-link" data-tool="fitToImage"
            @click="fitToType($event, 'fitToImage')">
            <svg-icon icon-class="fitToImage" style="font-size:20px;" />
          </button>
          <!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
        </div>
      </div>
      <!-- 测量标注 -->
      <div class="measureTool-wrapper">
        <div class="sideTool-title">{{ $t('trials:dicom-show:measurementLabeling') }}</div>
        <div class="sideTool-wrapper">
          <!-- 探针 -->
          <button :title="$t('trials:dicom-show:Probe')" class="btn-link" data-tool="Probe"
            @click="setToolActive($event, 'Probe')">
            <svg-icon icon-class="pixel" style="font-size:20px;" />
          </button>
          <!-- 长度测量 -->
          <button :title="$t('trials:dicom-show:Length')" class="btn-link" data-tool="Length"
            @click="setToolActive($event, 'Length')">
            <svg-icon icon-class="length" style="font-size:20px;" />
          </button>
          <!-- 角度测量 -->
          <button :title="$t('trials:dicom-show:Angle')" class="btn-link" data-tool="Angle"
            @click="setToolActive($event, 'Angle')">
            <svg-icon icon-class="angle" style="font-size:20px;" />
          </button>
          <!-- Cobb测量 -->
          <button :title="$t('trials:dicom-show:CobbAngle')" class="btn-link" data-tool="CobbAngle"
            @click="setToolActive($event, 'CobbAngle')">
            <svg-icon icon-class="cobb" style="font-size:20px;" />
          </button>
          <!-- 椭圆测量 -->
          <button :title="$t('trials:dicom-show:EllipticalRoi')" class="btn-link" data-tool="EllipticalRoi"
            @click="setToolActive($event, 'EllipticalRoi')">
            <svg-icon icon-class="oval" style="font-size:20px;" />
          </button>
          <!-- 矩形测量 -->
          <button :title="$t('trials:dicom-show:RectangleRoi')" class="btn-link" data-tool="RectangleRoi"
            @click="setToolActive($event, 'RectangleRoi')">
            <svg-icon icon-class="rectangle" style="font-size:20px;" />
          </button>
          <!-- 多边形标记 -->
          <button :title="$t('trials:dicom-show:FreehandRoi')" class="btn-link" data-tool="FreehandRoi"
            @click="setToolActive($event, 'FreehandRoi')">
            <svg-icon icon-class="polygon" style="font-size:20px;" />
          </button>
          <!-- 十字线 -->
          <button :title="$t('trials:dicom-show:Bidirectional')" class="btn-link" data-tool="Bidirectional"
            @click="setToolActive($event, 'Bidirectional')">
            <svg-icon icon-class="bidirection" style="font-size:20px;" />
          </button>
          <!-- 文字标注 -->
          <button :title="$t('trials:dicom-show:ArrowAnnotate')" class="btn-link" data-tool="ArrowAnnotate"
            @click="setToolActive($event, 'ArrowAnnotate')">
            <svg-icon icon-class="label" style="font-size:20px;" />
          </button>
          <!-- 清除测量和标记 -->
          <button :title="$t('trials:dicom-show:Eraser')" class="btn-link" data-tool="Eraser"
            @click="setToolActive($event, 'Eraser')">
            <svg-icon icon-class="clear" style="font-size:20px;" />
          </button>
          <!-- 截屏 -->
          <button :title="$t('trials:dicom-show:image')" class="btn-link" @click="currentDicomCanvas.saveImage()">
            <svg-icon icon-class="image" style="font-size:20px;" />
          </button>
          <!-- 标签 -->
          <button :title="$t('trials:dicom-show:tags')" class="btn-link" @click="currentDicomCanvas.showTags()">
            <svg-icon icon-class="dictionary" style="font-size:20px;" />
          </button>
        </div>
      </div>
      <div class="measureTool-wrapper">
        <!-- 播放 -->
        <div class="sideTool-title">{{ $t('trials:dicom-show:play') }}</div>
        <div class="sideTool-wrapper">
          <!-- 第一帧 -->
          <button class="btn-link" :title="$t('trials:dicom-show:firstframe')"
            @click="currentDicomCanvas.scrollPage(-9999)">
            <svg-icon icon-class="firstframe" style="font-size:20px;" />
          </button>
          <!-- 显示上一张影像 -->
          <button class="btn-link" :title="$t('trials:dicom-show:previousframe')"
            @click="currentDicomCanvas.scrollPage(-1)">
            <svg-icon icon-class="previousframe" style="font-size:20px;" />
          </button>
          <!-- 播放 -->
          <button class="btn-link" :title="$t('trials:dicom-show:play')" @click="clipPlay">
            <svg-icon :icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
              style="font-size:20px;" />
          </button>
          <!-- 下一帧 -->
          <button class="btn-link" :title="$t('trials:dicom-show:nextframe')" @click="currentDicomCanvas.scrollPage(1)">
            <svg-icon icon-class="nextframe" style="font-size:20px;" />
          </button>
          <!-- 最后一帧 -->
          <button class="btn-link" :title="$t('trials:dicom-show:lastframe')"
            @click="currentDicomCanvas.scrollPage(9999)">
            <svg-icon icon-class="lastframe" style="font-size:20px;" />
          </button>
          <select v-model="fps" class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
            <!-- 默认值 -->
            <option :value="5">5</option>
            <option :value="10">10</option>
            <option :value="15">15</option>
            <option :value="20">20</option>
            <option :value="30">30</option>
          </select>
        </div>
      </div>
      <div class="measureTool-wrapper">
        <!-- 颜色 -->
        <div class="sideTool-title">{{ $t('trials:dicom-show:color') }}</div>
        <div class="sideTool-wrapper">
          <!-- 预设窗位值 -->
          <label>{{ $t('trials:dicom-show:dicomCanvasWwwc') }}:</label>
          <select v-model="wwwcList[currentDicomCanvasIndex]" class="sidetool-select" style="width:100px"
            @change="setDicomCanvasWwwc($event)">
            <!-- 默认值 -->
            <option :value="-1">{{ $t('trials:dicom-show:default') }}</option>
            <!-- 自定义 -->
            <option :value="0">{{ $t('trials:dicom-show:custom') }}</option>
            <!-- 区域窗宽 -->
            <option :value="1" style="border-bottom:1px solid #fff;">{{ $t('trials:reading:button:wwwcRegion') }}
            </option>
            <option :value="2">CT Abdomen</option>
            <option :value="3">CT Angio</option>
            <option :value="4">CT Bone</option>
            <option :value="5">CT Brain</option>
            <option :value="6">CT Chest</option>
            <option :value="7">CT Lungs</option>
          </select>
        </div>

        <div class="sideTool-wrapper">
          <!-- 伪彩色 -->
          <label>{{ $t('trials:dicom-show:pseudocolor') }}:</label>
          <select v-model="colorList[currentDicomCanvasIndex]" class="sidetool-select" style="width:90px"
            @change="setColormap($event)">
            <!-- 默认值 -->
            <option value>{{ $t('trials:dicom-show:default') }}</option>
            <option v-for="(item, index) in colormapsList" :key="index" :value="item.id">{{ item.name }}</option>
          </select>
        </div>
      </div>

      <!-- 患者信息 -->
      <div class="measureTool-wrapper patient-form"
        v-if="type === 'Study' && modality && ['PT、CT', 'CT、PT', 'PET-CT'].includes(modality)">
        <div class="sideTool-title">{{ $t('trials:tab:patientData') }}</div>
        <div class="sideTool-wrapper">
          <el-form ref="patientForm" size="mini" :model="formData" :rules="rules" label-width="150"
            v-loading="formLoading">
            <!-- 性别 -->
            <el-form-item :label="$t('trials:ptData:label:patientSex')" prop="PatientSex">
              <el-select v-model="formData.PatientSex" :placeholder="$t('common:ruleMessage:select')"
                style="width: 100%" :disabled="!isEdit">
                <el-option :label="$t('trials:patientSex:male')" value="M"></el-option>
                <el-option :label="$t('trials:patientSex:female')" value="F"></el-option>
              </el-select>
            </el-form-item>
            <!-- 体重（kg） 例如 70.5-->
            <el-form-item :label="$t('trials:ptData:label:patientWeight')" prop="PatientWeight">
              <el-input v-model.number="formData.PatientWeight" :placeholder="$t('trials:patientWeight:eg')"
                style="width: 100%" :disabled="!isEdit"></el-input>
            </el-form-item>
            <!-- 总剂量（Bq） 例如 740000000-->
            <el-form-item :label="$t('trials:ptData:label:totalDose')" prop="RadionuclideTotalDose">
              <el-input v-model.number="formData.RadionuclideTotalDose" :placeholder="$t('trials:totalDose:eg')"
                style="width: 100%" :disabled="!isEdit"></el-input>
            </el-form-item>
            <!-- 半衰期（s） 例如 21600-->
            <el-form-item :label="$t('trials:ptData:label:halfLife')" prop="RadionuclideHalfLife">
              <el-input v-model.number="formData.RadionuclideHalfLife" :placeholder="$t('trials:halfLife:eg')"
                style="width: 100%" :disabled="!isEdit"></el-input>
            </el-form-item>
            <!-- 注射时间 HHMMSS-->
            <el-form-item :label="$t('trials:ptData:label:injectTime')" prop="RadiopharmaceuticalStartTime">
              <el-input v-model.trim="formData.RadiopharmaceuticalStartTime" :placeholder="$t('trials:injectTime:eg')"
                @blur="handleTimeBlur('RadiopharmaceuticalStartTime')" maxlength="6" style="width: 100%"
                @input="computeTimeRelation" :disabled="!isEdit"></el-input>
            </el-form-item>
            <!-- 成像时间 HHMMSS-->
            <el-form-item :label="$t('trials:ptData:label:acquisitionTime')" prop="AcquisitionTime">
              <el-input v-model.trim="formData.AcquisitionTime" @blur="handleTimeBlur('AcquisitionTime')" maxlength="6"
                :placeholder="$t('trials:injectTime:eg')" style="width: 100%" @input="computeTimeRelation"
                :disabled="!isEdit"></el-input>
            </el-form-item>
            <!-- 时间一致性检查 -->
            <!-- <el-form-item :label="$t('trials:ptData:label:timeCheck')">
              <el-input v-model="formData.TimeCheck" disabled style="width: 100%"></el-input>
            </el-form-item> -->

            <!-- 提交 -->
            <el-form-item style="margin-top: 20px;text-align: right;" v-if="isEdit">
              <el-button type="primary" @click="submitForm" size="small">{{ $t('trials:ptData:button:submit')
              }}</el-button>
            </el-form-item>
          </el-form>
        </div>
      </div>
    </div>
    <el-dialog v-if="customWwc.visible" :visible.sync="customWwc.visible" :close-on-click-modal="false"
      :title="customWwc.title" width="400px" custom-class="base-dialog-wrapper" append-to-body>
      <CustomWwwcForm @close="customWwc.visible = false" @setWwwc="setWwwc" />
    </el-dialog>
  </div>
</template>

<script>
import DicomCanvas from './DicomCanvas'
import CustomWwwcForm from './CustomWwwcForm'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools'
import Hammer from 'hammerjs'
// cornerstone.imageCache.setMaximumSizeBytes(0)

cornerstoneTools.external.cornerstone = cornerstone
cornerstoneTools.external.Hammer = Hammer
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
console.log(cornerstoneTools, 'cornerstoneTools')
console.log(cornerstone, 'cornerstone')
import '@/utils/dialog'
import { studyMaskImage, studyUndoMaskImage } from "@/api/reading"
import {
  getPatientInfo,
  editPatientInfo
} from '@/api/trials'
import { setPTClinicalDataForInstance, clearPTClinicalDataCache } from '@/utils/ptClinicalDataCache'
export default {
  name: 'DicomsViewer',
  components: {
    DicomCanvas,
    CustomWwwcForm,
  },
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    Comparison: {
      type: Boolean,
      default: false
    },
    modality: {
      type: String,
      default: ''
    }
  },
  watch: {
    modality: {
      immediate: true,
      handler(v) {
        if (v) {
          if (this.type === 'Study' && ['PT、CT', 'CT、PT', 'PET-CT'].includes(v)) {
            this.$nextTick(() => {
              this.getPatientInfo()
            })
          }
        }
      }
    }
  },
  data() {
    return {
      hasAnonymous: false,
      isAnonymous: false,
      isComparison: false,
      activeTool: '',
      activeItem: 'dicomCanvas0',
      layoutRow: 1,
      layoutCol: 1,
      currentDicomCanvasIndex: 0,
      currentDicomCanvas: {
        toolState: {
          clipPlaying: false,
        },
      },
      rowHeight: '100%',
      sync: {
        Wwwc: null,
      },
      colormapsList: [],
      rotateList: [],
      colorList: [],
      wwwcList: [],
      layout: null,
      seriesList: [],
      series: {},
      customWwc: { visible: false, title: null },
      fps: 15,
      formData: {
        Id: '',
        PatientSex: '',
        PatientWeight: null,
        RadionuclideTotalDose: null,
        RadionuclideHalfLife: null,
        RadiopharmaceuticalStartTime: '',
        AcquisitionTime: '',
        TimeCheck: ''
      },
      rules: {
        PatientSex: [
          { required: true, message: this.$t('common:ruleMessage:select'), trigger: 'change' }
        ],
        PatientWeight: [
          { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
          { type: 'number', min: 0, message: this.$t('trials:ptData:ruleMessage:number1'), trigger: 'blur' }//数值必须大于0
        ],
        RadionuclideTotalDose: [
          { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
          { type: 'number', min: 0, message: this.$t('trials:ptData:ruleMessage:number1'), trigger: 'blur' }//数值必须大于0
        ],
        RadionuclideHalfLife: [
          { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
          { type: 'number', min: 0, message: this.$t('trials:ptData:ruleMessage:number1'), trigger: 'blur' }
        ],
        RadiopharmaceuticalStartTime: [
          { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
          { validator: this.validateDicomTime, trigger: 'blur' }
        ],
        AcquisitionTime: [
          { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
          { validator: this.validateDicomTime, trigger: 'blur' },
          // 自定义校验：确保成像时间不早于注射时间
          { validator: this.validateTime, trigger: 'blur' }
        ]
      },
      formLoading: false,
      type: '',
      isEdit: 0
    }
  },
  computed: {
    isMultiple() {
      return this.series?.instanceInfoList[0]?.NumberOfFrames > 1
    }
  },
  mounted() {
    let type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
    this.hasAnonymous = type === 'Study'
    this.customWwc = {
      visible: false,
      title: this.$t('DicomViewer:data:customWwc'),
    }
    this.rotateList[0] = '1'
    this.colorList[0] = ''
    this.wwwcList[0] = '-1'
    this.colormapsList = cornerstone.colors.getColormapsList()
    this.currentDicomCanvas = this.$refs['dicomCanvas0']
    this.type = this.$route.query.type
    this.isEdit = parseInt(this.$route.query.showDelete) || parseInt(this.$route.query.showEdit)
  },
  beforeDestroy() {
    clearPTClinicalDataCache()
  },

  methods: {
    setToolsPassive() {
      const elements = document.querySelectorAll('.dicom-item')
      const scope = this
      Array.from(elements).forEach((element, index) => {
        if (element.style.display !== 'none') {
          scope.$refs[`dicomCanvas${index}`].setToolPassive(scope.activeTool)
        }
      })
      scope.activeTool = null
    },
    comparison(f) {
      this.setToolsPassive()
      if (f) {
        this.$refs[`dicomCanvas0`].getNote_RectangleRoi().then(obj => {
          let { image } = obj
          let instanceInfo = this.series.instanceInfoList.find(item => {
            let s1 = item.ImageId.split("?")[0]
            let s2 = image.imageId.split("?")[0]
            return s1 === s2
          })
          if (!instanceInfo.IsMasked) return this.$confirm(this.$t("DicomViewer:anonymous:notMasked"))
          this.changeLayout('1x2')
          this.isComparison = f
          this.$emit("update:Comparison", f)
          let serie = {}
          Object.keys(this.series).forEach(key => {
            if (key !== 'instanceInfoList' && key !== 'imageIds') {
              serie[key] = this.series[key]
            }
          })
          let imageId = image.imageId
          let newImageId = imageId.split("?")[0].split(".MaskDicom_")[0] + "?" + imageId.split("?")[1]
          let info0 = {}, info1 = {}
          Object.keys(instanceInfo).forEach(key => {
            info0[key] = instanceInfo[key]
            info1[key] = instanceInfo[key]
          })
          info0.ImageId = imageId
          info1.ImageId = newImageId
          let dicomCanvas0_info = Object.assign({
            instanceInfoList: [
              info0
            ],
            imageIds: [imageId]
          }, serie)
          let dicomCanvas1_info = Object.assign({
            instanceInfoList: [
              info1
            ],
            imageIds: [newImageId]
          }, serie)
          this.$refs[`dicomCanvas0`].loadImageStack(dicomCanvas0_info, this.$t('DicomViewer:anonymous:after'))
          this.$refs[`dicomCanvas1`].loadImageStack(dicomCanvas1_info, this.$t('DicomViewer:anonymous:before'))
        })
      } else {
        this.isComparison = f
        this.$emit("update:Comparison", f)
        this.changeLayout('1x1')
        this.$refs[`dicomCanvas0`].loadImageStack(this.series)
      }
    },
    recovery(isAll = false) {
      // if (this.isComparison) return false
      if (this.isAnonymous) {
        this.comparison(false)
      }
      this.setToolsPassive()
      this.$refs[`dicomCanvas0`].getNote_RectangleRoi().then(async obj => {
        let { image } = obj
        let instanceInfo = this.series.instanceInfoList.find(item => {
          let s1 = item.ImageId.split("?")[0]
          let s2 = image.imageId.split("?")[0]
          return s1 === s2
        })
        if ((!instanceInfo.IsMasked && !isAll) || (isAll && this.series.instanceInfoList.every(item => !item.IsMasked))) return this.$confirm(this.$t("DicomViewer:anonymous:notMasked"))
        let data = {
          // SeriesId: this.series.seriesId,
          instanceIdList: [instanceInfo.Id]
        }
        if (isAll) {
          data.SeriesId = this.series.seriesId
          delete data.instanceIdList
        }
        let res = await this.studyUndoMaskImage(data)
        if (!res) return false
        this.$emit("update:loading", true)
        let isMultiple = false
        if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1 && isAll === false) {
          isAll = true;
          isMultiple = true;
        }
        if (!isAll) {
          let strs = image.imageId.split("?")
          let newImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${res[0].Path}?${strs[1]}`
          this.series.instanceInfoList.some(item => {
            if (item.Id === instanceInfo.Id) {
              item.ImageId = newImageId
              item.IsMasked = false
            }
            return item.Id === instanceInfo.Id
          })
          let index = this.series.imageIds.findIndex(item => item === image.imageId)
          this.series.imageIds.splice(index, 1, newImageId)
          await this.$refs[`dicomCanvas0`].reloadImage(newImageId)
        } else {

        }
        this.$emit('loadStudy', this.series.seriesId)
        this.$emit("update:loading", false)
      })
    },
    anonymousImage(isAll = false) {
      if (this.isComparison) return false
      this.setToolsPassive()
      this.$refs[`dicomCanvas0`].getNote_RectangleRoi().then(async obj => {
        let { toolInfo, image } = obj
        if (!toolInfo || toolInfo.data.length <= 0) return this.$confirm(this.$t("DicomViewer:anonymous:notMark"))
        let instanceInfo = this.series.instanceInfoList.find(item => {
          let s1 = item.ImageId.split("?")[0]
          let s2 = image.imageId.split("?")[0]
          return s1 === s2
        })
        let data = {
          // SeriesId: this.series.seriesId,
          instanceIdList: [instanceInfo.Id],
          MaskRegionList: []
        }
        if (isAll) {
          data.SeriesId = this.series.seriesId
          delete data.instanceIdList
        }
        toolInfo.data.forEach(item => {
          let currentStart = item.handles.start
          let currentEnd = item.handles.end
          let start = {
            x: currentStart.x > currentEnd.x ? Math.round(currentEnd.x) : Math.round(currentStart.x),
            y: currentStart.y > currentEnd.y ? Math.round(currentEnd.y) : Math.round(currentStart.y),
          }
          let end = {
            x: currentStart.x > currentEnd.x ? Math.round(currentStart.x) : Math.round(currentEnd.x),
            y: currentStart.y > currentEnd.y ? Math.round(currentStart.y) : Math.round(currentEnd.y),
          }
          let width = end.x - start.x
          let height = end.y - start.y
          data.MaskRegionList.push({
            X: start.x,
            Y: start.y,
            Width: width,
            Height: height
          })
        })
        let res = await this.studyMaskImage(data)
        if (!res || res.length <= 0) return this.$confirm(this.$t("DicomViewer:anonymous:studyMaskImageFail"))
        this.$emit("update:loading", true)
        let isMultiple = false
        if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1 && isAll === false) {
          isAll = true;
          isMultiple = true;
        }
        if (!isAll) {
          let strs = image.imageId.split("?")
          let newImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${res[0].Path}?${strs[1]}`
          this.series.instanceInfoList.some(item => {
            if (item.Id === instanceInfo.Id) {
              item.ImageId = newImageId
              item.IsMasked = true
            }
            return item.Id === instanceInfo.Id
          })
          let index = this.series.imageIds.findIndex(item => item === image.imageId)
          this.series.imageIds.splice(index, 1, newImageId)
          await this.$refs[`dicomCanvas0`].reloadImage(newImageId)
        } else {

        }
        this.$refs[`dicomCanvas0`].removeNote_RectangleRoi()
        setTimeout(() => {
          this.$emit('loadStudy', this.series.seriesId)
          this.$emit("update:loading", false)
        }, 500)
      })
    },
    openAnonymous() {
      this.isAnonymous = !this.isAnonymous
      if (!this.isAnonymous) {
        const elements = document.querySelectorAll('.dicom-item')
        const scope = this
        Array.from(elements).forEach((element, index) => {
          if (element.style.display !== 'none') {
            scope.$refs[`dicomCanvas${index}`].setToolPassive(scope.activeTool)
          }
        })
        scope.activeTool = null
      } else {
        this.activateDicomCanvas(0)
        this.changeLayout('1x1')
      }
    },
    async studyMaskImage(data) {
      try {
        this.$emit("update:loading", true)
        let res = await studyMaskImage(data)
        this.$emit("update:loading", false)
        if (res.IsSuccess) {
          return res.Result.OkList
        }
        return false
      } catch (err) {
        console.log(err)
        this.$emit("update:loading", false)
        return false
      }
    },
    async studyUndoMaskImage(data) {
      try {
        this.$emit("update:loading", true)
        let res = await studyUndoMaskImage(data)
        this.$emit("update:loading", false)
        if (res.IsSuccess) {
          return res.Result.OkList
        }
        return false
      } catch (err) {
        console.log(err)
        this.$emit("update:loading", false)
        return false
      }
    },
    loadImageStack(dicomSeries) {
      this.currentDicomCanvas.toolState.clipPlaying = false
      this.$nextTick(() => {
        this.series = Object.assign({}, dicomSeries)
        this.seriesList = [this.series]
        this.currentDicomCanvas.loadImageStack(this.series)
        if (
          this.formData.PatientWeight != null ||
          this.formData.RadionuclideTotalDose != null ||
          this.formData.RadionuclideHalfLife != null ||
          this.formData.RadiopharmaceuticalStartTime != null ||
          this.formData.AcquisitionTime != null
        ) {
          this.cachePtClinicalDataToInstances()
        }
      })
    },
    loadOtherImageStack(seriesList) {
      this.$nextTick(() => {
        this.seriesList = seriesList
        const elements = document.querySelectorAll('.dicom-item')
        Array.from(elements).forEach((element, index) => {
          const canvasIndex = element.getAttribute('data-index')
          if (index < seriesList.length && element.style.display !== 'none') {
            const series = Object.assign({}, seriesList[index])
            this.$refs[`dicomCanvas${canvasIndex}`].loadImageStack(series)
          }
        })
        if (
          this.formData.PatientWeight != null ||
          this.formData.RadionuclideTotalDose != null ||
          this.formData.RadionuclideHalfLife != null ||
          this.formData.RadiopharmaceuticalStartTime != null ||
          this.formData.AcquisitionTime != null
        ) {
          this.cachePtClinicalDataToInstances()
        }
      })
    },
    activateDicomCanvas(index) {
      if (index !== this.currentDicomCanvasIndex) {
        this.currentDicomCanvasIndex = index
        this.currentDicomCanvas = this.$refs[`dicomCanvas${index}`]
        this.currentDicomCanvas.tabIndex = 0
        this.activeItem = `dicomCanvas${index}`
        if (this.sync.ReferenceLines) {
          if (this.sync['ReferenceLines']) {
            const elements = this.sync['ReferenceLines'].getSourceElements()
            if (elements.length > 0) {
              this.$refs[`dicomCanvas${index}`].removeTarget(
                this.sync['ReferenceLines']
              )
              this.sync['ReferenceLines'].addTarget(elements[0])
              this.sync['ReferenceLines'].removeSource(elements[0])
              this.$refs[`dicomCanvas${index}`].addSourceElement(
                this.sync['ReferenceLines']
              )
            }
          }
        }
        if (!this.rotateList[this.currentDicomCanvasIndex]) {
          this.rotateList[this.currentDicomCanvasIndex] = '1'
        }
        if (!this.colorList[this.currentDicomCanvasIndex]) {
          this.colorList[this.currentDicomCanvasIndex] = ''
        }
        if (!this.wwwcList[this.currentDicomCanvasIndex]) {
          this.wwwcList[this.currentDicomCanvasIndex] = '-1'
        }
      }
    },
    changeLayout(event) {
      const arr = event.target ? event.target.value.split('x') : event.split('x')
      this.layoutRow = parseInt(arr[0])
      this.layoutCol = parseInt(arr[1])
      this.rowHeight = 100 / this.layoutRow + '%'
      this.$forceUpdate()
      this.$nextTick(() => {
        const elements = document.querySelectorAll('.cornerstone-element')
        Array.from(elements).forEach((element) => {
          cornerstone.enable(element)
          cornerstone.resize(element)
        })
      })
    },
    setFullScreen(e) {
      if (this.layoutRow === 1 && this.layoutCol === 1) return
      if (this.layout) {
        e.currentTarget.classList.remove('dicom-item-fullscreen')
        const arr = this.layout.split('x')
        this.layoutRow = parseInt(arr[0])
        this.layoutCol = parseInt(arr[1])
        this.rowHeight = 100 / this.layoutRow + '%'
        this.$forceUpdate()
        this.$nextTick(() => {
          const elements = document.querySelectorAll('.cornerstone-element')
          Array.from(elements).forEach((element) => {
            cornerstone.enable(element)
            cornerstone.resize(element)
          })
        })
        this.layout = null
      } else {
        this.layout = `${this.layoutRow}x${this.layoutCol}`
        e.currentTarget.classList.add('dicom-item-fullscreen')
        cornerstone.enable(e.currentTarget.children[0])
        cornerstone.resize(e.currentTarget.children[0])
      }
    },
    fillColor() {
      const elements = document.querySelectorAll('.dicom-item')
      const scope = this
      Array.from(elements).forEach((element, index) => {
        if (element.style.display !== 'none') {
          scope.$refs[`dicomCanvas${index}`].fillColor()
        }
      })
    },
    setToolActive(e, toolName, isNotSetClassName = false) {
      const elements = document.querySelectorAll('.dicom-item')
      if (isNotSetClassName) {
        const scope = this
        if (scope.activeTool) {
          Array.from(elements).forEach((element, index) => {
            if (element.style.display !== 'none') {
              scope.$refs[`dicomCanvas${index}`].setToolPassive(scope.activeTool)
            }
          })
        }
        if (scope.activeTool === toolName) return scope.activeTool = null
        scope.activeTool = toolName
        return Array.from(elements).forEach((element, index) => {
          if (element.style.display !== 'none') {
            scope.$refs[`dicomCanvas${index}`].setToolActive(toolName)
          }
        })
      }
      if (e.currentTarget.classList.contains('activeTool')) {
        e.currentTarget.classList.remove('activeTool')
        const scope = this
        scope.activeTool = null
        Array.from(elements).forEach((element, index) => {
          if (element.style.display !== 'none') {
            scope.$refs[`dicomCanvas${index}`].setToolPassive(toolName)
          }
        })
      } else {
        const toolButtons = document.querySelectorAll('[data-tool]')
        Array.from(toolButtons).forEach((toolBtn) => {
          toolBtn.classList.remove('activeTool')
        })
        e.currentTarget.classList.add('activeTool')

        const scope = this
        scope.activeTool = toolName
        Array.from(elements).forEach((element, index) => {
          if (element.style.display !== 'none') {
            scope.$refs[`dicomCanvas${index}`].setToolActive(toolName)
          }
        })
      }
    },
    setDicomCanvasWwwc(event) {
      this.wwwcList[this.currentDicomCanvasIndex] = event.target.value
      const type = parseInt(event.target.value)
      if (type === -1) {
        // 默认值
        this.currentDicomCanvas.resetWwwc()
      } else if (type === 0) {
        // 自定义
        this.customWwc.visible = true
      } else if (type === 1) {
        // 区域窗宽
        this.currentDicomCanvas.setToolActive('WwwcRegion')
      } else if (type === 2) {
        this.currentDicomCanvas.setWwwc(400, 60)
      } else if (type === 3) {
        this.currentDicomCanvas.setWwwc(600, 300)
      } else if (type === 4) {
        this.currentDicomCanvas.setWwwc(1500, 300)
      } else if (type === 5) {
        this.currentDicomCanvas.setWwwc(80, 40)
      } else if (type === 6) {
        this.currentDicomCanvas.setWwwc(400, 40)
      } else if (type === 7) {
        this.currentDicomCanvas.setWwwc(1500, -400)
      }
    },
    setWwwc(v) {
      this.currentDicomCanvas.setWwwc(v.ww, v.wc)
      this.customWwc.visible = false
    },
    toggleInvert() {
      this.currentDicomCanvas.toggleInvert()
    },
    setDicomCanvasRotate(value) {
      const type = parseInt(value)
      if (type === 1) {
        this.currentDicomCanvas.resetRotate()
      } else if (type === 2) {
        this.currentDicomCanvas.setRotate(true, false, 0, type)
      } else if (type === 3) {
        this.currentDicomCanvas.setRotate(false, true, 0, type)
      } else if (type === 4) {
        this.currentDicomCanvas.setRotate(false, false, -90, type)
      } else if (type === 5) {
        this.currentDicomCanvas.setRotate(false, false, 90, type)
      }
    },
    setColormap(event) {
      this.colorList[this.currentDicomCanvasIndex] = event.target.value
      this.currentDicomCanvas.setColormap(event.target.value)
    },
    setDicomCanvasfps(event) {
      this.currentDicomCanvas.setFps(event.target.value)
    },
    clipPlay() {
      this.currentDicomCanvas.setFps(this.fps)
      this.currentDicomCanvas.toggleClipPlay()
    },
    fitToType(e, type) {
      const toolButtons = document.querySelectorAll('[data-tool]')
      Array.from(toolButtons).forEach((toolBtn) => {
        toolBtn.classList.remove('activeTool')
      })
      e.currentTarget.classList.add('activeTool')
      if (type === 'fitToWindow') {
        this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`].fitToWindow()
      } else {
        this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`].fitToImage()
      }
    },
    setAnnotationSync(e) {
      if (this.layoutRow * this.layoutCol === 1) {
        return
      }
      this.resetSync('annotationSync')
      let isActive = true
      const toolBtn = e.currentTarget
      if (toolBtn.classList.contains('activeTool')) {
        toolBtn.classList.remove('activeTool')
        isActive = false
      } else {
        toolBtn.classList.add('activeTool')
      }
      if (!this.sync.annotationSync) {
        this.sync.annotationSync = new cornerstoneTools.Synchronizer(
          'cornerstoneimagerendered',
          cornerstoneTools.updateImageSynchronizer
        )
      }
      const scope = this
      const elements = document.querySelectorAll('.dicom-item')
      Array.from(elements).forEach((element, index) => {
        if (element.style.display !== 'none') {
          if (isActive) {
            if (index !== scope.currentDicomCanvasIndex) {
              scope.$refs[`dicomCanvas${index}`].addTargetElement(
                scope.sync['annotationSync']
              )
            } else {
              scope.$refs[`dicomCanvas${index}`].addSourceElement(
                scope.sync['annotationSync']
              )
            }
            scope.$refs[`dicomCanvas${index}`].activeAnnotationSync(
              scope.sync.annotationSync
            )
          } else {
            scope.$refs[`dicomCanvas${index}`].disabledAnnotationSync(
              scope.sync.annotationSync
            )
          }
        }
      })
      if (!isActive) {
        scope.sync.annotationSync = null
      }
    },
    resetSync(prop) {
      for (const key in this.sync) {
        if (key !== prop) {
          if (this.sync[prop]) {
            this.sync[prop] = null
          }
        }
      }
    },
    // 时间一致性校验
    validateTime(rule, value, callback) {
      const { RadiopharmaceuticalStartTime } = this.formData
      const acquireSeconds = this.timeToSeconds(value)
      const startSeconds = this.timeToSeconds(RadiopharmaceuticalStartTime)
      if (acquireSeconds !== null && startSeconds !== null && acquireSeconds < startSeconds) {
        callback(new Error(this.$t('trials:ptData:ruleMessage:number3')))//成像时间不能早于注射时间
      } else {
        callback()
      }
    },
    validateDicomTime(rule, value, callback) {
      if (value === undefined || value === null || value === '') {
        callback()
        return
      }
      const raw = String(value).trim()
      if (!/^\d{1,6}$/.test(raw)) {
        callback(new Error(this.$t('trials:ptData:ruleMessage:number2')))
        return
      }
      const normalized = this.normalizeClinicalTime(raw)
      if (!this.isValidDicomTime(normalized)) {
        callback(new Error(this.$t('trials:ptData:ruleMessage:number4')))//请输入有效时间（HHMMSS）
        return
      }
      callback()
    },
    normalizeClinicalTime(value) {
      if (value === undefined || value === null || value === '') return ''
      const digits = String(value).trim().replace(/[^\d]/g, '')
      if (!digits) return ''
      return digits.slice(0, 6).padStart(6, '0')
    },
    isValidDicomTime(value) {
      if (!/^\d{6}$/.test(String(value || ''))) return false
      const normalized = String(value)
      const hh = Number(normalized.slice(0, 2))
      const mm = Number(normalized.slice(2, 4))
      const ss = Number(normalized.slice(4, 6))
      return hh >= 0 && hh <= 23 && mm >= 0 && mm <= 59 && ss >= 0 && ss <= 59
    },
    timeToSeconds(value) {
      const normalized = this.normalizeClinicalTime(value)
      if (!this.isValidDicomTime(normalized)) return null
      const hh = Number(normalized.slice(0, 2))
      const mm = Number(normalized.slice(2, 4))
      const ss = Number(normalized.slice(4, 6))
      return hh * 3600 + mm * 60 + ss
    },
    handleTimeBlur(field) {
      const value = this.formData[field]
      if (value === undefined || value === null || value === '') return
      this.formData[field] = this.normalizeClinicalTime(value)
      this.computeTimeRelation()
    },
    normalizeTimeFields() {
      this.formData.RadiopharmaceuticalStartTime = this.normalizeClinicalTime(
        this.formData.RadiopharmaceuticalStartTime
      )
      this.formData.AcquisitionTime = this.normalizeClinicalTime(
        this.formData.AcquisitionTime
      )
      this.computeTimeRelation()
    },
    computeTimeRelation() {
      const startTime = this.formData.RadiopharmaceuticalStartTime
      const acquireTime = this.formData.AcquisitionTime

      if (!startTime || !acquireTime) {
        this.formData.TimeCheck = ''
        return
      }

      const startSeconds = this.timeToSeconds(startTime)
      const acquireSeconds = this.timeToSeconds(acquireTime)
      if (startSeconds === null || acquireSeconds === null) {
        this.formData.TimeCheck = ''
        return
      }

      if (startSeconds <= acquireSeconds) {
        this.formData.TimeCheck = this.$t('trials:ptData:timeCheck:val1') //注射时间 ≤ 成像时间
      } else {
        this.formData.TimeCheck = this.$t('trials:ptData:timeCheck:val2') //注射时间 > 成像时间
      }
    },
    async getPatientInfo() {
      try {
        this.formLoading = true
        let studyId = this.$route.query.studyId
        let res = await getPatientInfo({ studyId: studyId })
        this.formData = {
          Id: res.Result.Id || '',
          PatientSex: res.Result.PatientSex || '',
          PatientWeight: parseFloat(res.Result.PatientWeight) || null,
          RadionuclideTotalDose: parseFloat(res.Result.RadionuclideTotalDose) || null,
          RadionuclideHalfLife: parseFloat(res.Result.RadionuclideHalfLife) || null,
          RadiopharmaceuticalStartTime: this.normalizeClinicalTime(res.Result.RadiopharmaceuticalStartTime),
          AcquisitionTime: this.normalizeClinicalTime(res.Result.AcquisitionTime),
          TimeCheck: ''
        }
        this.computeTimeRelation()
        // 缓存 PT 临床数据：用于 2D SUV 计算时优先使用接口/人工录入值
        this.cachePtClinicalDataToInstances()
        this.formLoading = false
      } catch (e) {
        this.formLoading = false
        console.log(e)
      }
    },
    cachePtClinicalDataToInstances() {
      const clinicalData = {
        PatientSex: this.formData.PatientSex,
        PatientWeight: this.formData.PatientWeight,
        RadionuclideTotalDose: this.formData.RadionuclideTotalDose,
        RadionuclideHalfLife: this.formData.RadionuclideHalfLife,
        RadiopharmaceuticalStartTime: this.formData.RadiopharmaceuticalStartTime,
        AcquisitionTime: this.formData.AcquisitionTime
      }
      const seriesList = Array.isArray(this.seriesList) ? this.seriesList : []
      seriesList.forEach(series => {
        const instanceInfoList = series?.instanceInfoList
        if (Array.isArray(instanceInfoList) && instanceInfoList.length > 0) {
          instanceInfoList.forEach(instance => {
            if (instance && instance.Id != null) {
              setPTClinicalDataForInstance(instance.Id, clinicalData)
            }
          })
          return
        }
        const imageIds = series?.imageIds
        if (Array.isArray(imageIds) && imageIds.length > 0) {
          imageIds.forEach(imageId => {
            const instanceId = this.getInstanceIdFromImageId(imageId)
            if (instanceId) {
              setPTClinicalDataForInstance(instanceId, clinicalData)
            }
          })
        }
      })
    },
    getInstanceIdFromImageId(imageId) {
      try {
        const qIndex = String(imageId).indexOf('?')
        if (qIndex === -1) return null
        const params = new URLSearchParams(String(imageId).slice(qIndex + 1))
        const instanceId = params.get('instanceId')
        return instanceId ? String(instanceId).trim() : null
      } catch (e) {
        return null
      }
    },
    refreshDicomAfterClinicalDataChanged() {
      // 患者信息保存后，强制刷新画布与标注统计，确保 SUV 等数据显示使用最新的 PT 临床数据口径
      const toolTypes = [
        'Probe',
        'RectangleRoi',
        'EllipticalRoi',
        'FreehandRoi',
        'Bidirectional',
        'Length',
        'ArrowAnnotate',
        'Angle',
        'CobbAngle'
      ]
      const elements = document.querySelectorAll('.dicom-item')
      Array.from(elements).forEach((wrapper) => {
        const index = wrapper.getAttribute('data-index')
        const canvasComp = index !== null ? this.$refs[`dicomCanvas${index}`] : null
        const element = canvasComp?.$refs?.canvas
        if (!element) return
        toolTypes.forEach((toolType) => {
          const toolState = cornerstoneTools.getToolState(element, toolType)
          if (toolState && Array.isArray(toolState.data)) {
            toolState.data.forEach((d) => {
              if (d && typeof d === 'object') {
                d.invalidated = true
              }
            })
          }
        })
        cornerstone.updateImage(element, true)
      })
    },
    async submitForm() {
      try {
        let valid = await this.$refs.patientForm.validate()
        if (!valid) return
        this.normalizeTimeFields()
        this.formLoading = true
        let res = await editPatientInfo(this.formData)
        this.formLoading = false
        if (res.IsSuccess) {
          this.$message.success(this.$t('common:message:savedSuccessfully'))
          this.cachePtClinicalDataToInstances()
          this.refreshDicomAfterClinicalDataChanged()
        }
      } catch (e) {
        this.formLoading = false
        console.log(e)
      }

    }
  }
}
</script>
<style lang="scss">
.Anonymous {
  position: absolute;
  border-radius: 5px;
  bottom: 30px;
  left: 5%;
  right: 5%;
  width: 90%;
  height: 60px;
  padding: 0 10px;
  background-color: rgba(255, 255, 255, .2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 2000;

  .btn {
    width: 12%;
    text-align: center;
    height: 40px;
    line-height: 30px;
    border-radius: 15px;
    cursor: pointer;
    padding: 5px 10px;
    color: #428bca;
    background: #ecf3fa;
    border-color: #b3d1ea;
  }

  .activeBtn {
    background: #428bca;
    border-color: #428bca;
    color: #fff;
  }

  // &:hover {
  //   background-color: rgba(255, 255, 255, .5);
  // }
}


.isNoted {
  cursor: not-allowed;
}
</style>
<style>
.dicom-wrapper {
  display: flex;
  height: 100%;
}

.dicom-wrapper .case-dialog-class {
  position: fixed;
  left: 25%;
  pointer-events: auto;
  display: block;
  overflow: auto;
}

.dicom-wrapper .case-dialog-div {
  pointer-events: none;
}

.dicom-wrapper .case-dialog-class .el-dialog__body {
  max-height: 300px;
  overflow-y: auto;
}

.dicom-wrapper .el-dialog__header {
  padding: 15px;
}

.dicom-wrapper .el-dialog__body {
  padding: 10px 20px;
}

.dicom-viewer {
  display: flex;
  flex-direction: column;
  flex: 1;
  position: relative;
}





.dicom-tools .btnBox {
  display: inline-block;
  width: 80px;
  text-align: center;
  height: 30px;
  line-height: 20px;
  border-radius: 15px;
  color: #428bca;
  background: #ecf3fa;
  border-color: #b3d1ea;
  cursor: pointer;
  padding: 5px 10px;
  border: 1px solid rgba(255, 255, 255, .7);
  margin: 5px;
}

.dicom-tools .activeBtnBox {
  background: #428bca;
  border-color: #428bca;
  color: #fff;
}

.dicom-wrapper .dicom-row {
  display: flex;
  flex-direction: row;
  flex: 1;
  width: 100%;
}

.dicom-wrapper .dicom-item {
  position: relative;
  width: 0;
  flex: 1;
  flex-shrink: 1;
  box-sizing: border-box;
  padding: 5px;
  border: 1px solid #c8c8c8;
}

.dicom-wrapper .activeItem {
  border: 2px solid chocolate;
}

.dicom-item-fullscreen {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

.dicom-wrapper ::-webkit-scrollbar {
  width: 7px;
  height: 7px;
}

.dicom-wrapper ::-webkit-scrollbar-thumb {
  border-radius: 10px;
  background: gray;
}

.dicom-wrapper .dicom-tools {
  /* display: flex;
  flex-direction: column; */
  width: 300px;
  height: 100%;
  background-color: #323232;
  margin: 0;
  padding: 0;
  margin-left: 2px;
  /* border: 1px solid blueviolet; */
  color: #d0d0d0;
  font-size: 13px;
  overflow-y: auto;
}

.dicom-wrapper .measure-wrapper {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

.measure-wrapper .measure-list {
  flex: 1;
  overflow-y: auto;
}

.measure-list-header {
  padding: 2px 0px;
  border-bottom: 1px solid gray;
}

.measure-wrapper ul {
  margin: 0;
  padding: 0 5px;
  list-style: none;
}

.measure-wrapper ul li {
  height: 20px;
  display: flex;
  justify-content: space-between;
  margin-bottom: 5px;
  text-align: center;
}

.measure-wrapper select {
  height: 20px;
  background-color: rgba(0, 0, 0, 0);
  /* color: #323232; */
  border-radius: 4px;
  font-size: 13px;
  color: #606626;
}

.measure-wrapper select>option {
  color: #323232;
}

/* .measure-wrapper select {
  height: 20px;
  background-color: rgba(0, 0, 0, 0);
  color: #d0d0d0;
  border-radius: 4px;
}
.measure-wrapper select > option {
  background-color: #323232;
} */
.dicom-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid #333333;
}

.dicom-canvas.active {
  border: 1px solid #337ab7;
}

.sideTool-title {
  padding: 5px 8px;
  background-color: #525252;
  color: #bebdbd;
  font-size: 14px;
  margin: 4px;
}

.sideTool-wrapper {
  border-bottom: 1px solid gray;
  margin: 0px 4px;
  padding: 4px;
  font-size: 12px;
}

.sideTool-wrapper .btn {
  font-size: 12px;
}

.sidetool-select {
  height: 30px;
  background-color: rgba(0, 0, 0, 0);
  color: #d0d0d0;
  border-radius: 4px;
}

.sidetool-select>option {
  background-color: #323232;
}

.sideTool-wrapper button.btn-link {
  height: 40px;
  padding: 8px !important;
  border: 1px solid rgba(37, 37, 37, 1);
  margin: 1px 1px;
}

.sideTool-wrapper .btn-link {
  display: inline-block;
  height: 40px;
  padding: 8px !important;
  border: 1px solid rgba(37, 37, 37, 1);
  margin: 1px 1px;
}

.dicom-wrapper .btn-group {
  position: relative;
  display: inline-block;
  height: 30px;
  padding: 6px 3px;
  vertical-align: middle;
  margin: 1px 1px;
  border-radius: 3px;
  font-size: 12px;
  font-weight: 500;
  color: silver;
  line-height: 20px !important;
  background: rgba(50, 50, 50, 1);
  border: 1px solid rgba(37, 37, 37, 1);
  min-height: 30px;
}

.dicom-wrapper .btn-group .btn-left {
  position: relative;
  float: left;
  padding: 1px !important;
  margin-left: 0;
  border-bottom-right-radius: 0;
  border-top-right-radius: 0;
}

.dicom-wrapper .activeTool {
  background: #16477b90 !important;
  border: none;
}

.dicom-wrapper .btn-link {
  color: #cccccc;
  background-color: #ffffff00;
  cursor: pointer;
}

.dicom-wrapper .btn-submit {
  cursor: pointer;
  /* background-color: #eeeeee; */
  background: #eeeeee;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  color: #606266;
  font-size: 13px;
}

/* .dicom-wrapper .btn-link:hover,
.dicom-wrapper .btn-link:focus,
.dicom-wrapper .btn-link:active {
  border-color: transparent;
  background-color: transparent;
} */
.dicom-wrapper .iconHover:hover {
  color: red;
}

.dicom-wrapper .dropdown {
  position: relative;
  display: inline-block;
}

.dicom-wrapper .dropdown-content {
  display: none;
  position: absolute;
  left: -20px;
  top: 40px;
  color: #d0d0d0;
  background-color: #323232;
  min-width: 100px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  border: 1px solid #4e4e4e;
  padding: 5px;
}

.dicom-wrapper .dropdown:hover .dropdown-content {
  display: block;
}

.dicom-wrapper .dropdown-content div {
  height: 25px;
  line-height: 25px;
  cursor: point;
}

.dicom-wrapper .dropdown-content div:hover {
  background-color: #16477b90;
}

.patient-form .el-form-item {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.patient-form .el-form-item__label {
  color: #d0d0d0;
  flex: 0 0 150px;
  text-align: left;
}

.patient-form .el-form-item__content {
  flex: 1;
  margin-left: 0;
}

.patient-form .el-input.is-disabled .el-input__inner {
  background-color: #424244;
}

.patient-form .el-input .el-input__inner {
  background-color: #323232;
  color: #d0d0d0;
}
</style>
