<template>
  <div class="detection-container-box">
    <Header />
    <div class="displaycontainer">
      <div class="displayleft">
        <img src="@/assets/detection/progress.png" alt=""  style=" margin-left:10px;margin-right:15px">
        <div style="
          font-size: 18px;
          font-weight: 700;
          font-style: normal;
          color: #3BF2C6;"
         >检测中...</div>
        <div class="patientInfotop1">{{ patientInfo.name }}</div>
        <div style="font-size: 20px;"> {{ patientInfo.gender }}</div>
        <div class="username-line"></div>
        <div style="font-size: 20px;">{{ calculateAge(patientInfo.birth_date) }}岁</div>
        <el-button type="primary" class="endbutton" @click="endClick">结束检测</el-button>
      </div>
      <div class="displayleft">
        <div class="icon-box" :title="remoteStatus =='未连接'?'截图':'截图（有遥控器）'" @click="saveDetectionData">
          <img src="@/assets/detection/screenshot.png" alt="">
        </div>
        <div class="icon-box" @click="isPhotoAlbum = true" title="相册">
          <img src="@/assets/detection/photoalbum.svg" alt="">
        </div>
        <div v-if="!isStartVideo" class="icon-box" @click="startVideoClick" 
        :title="remoteStatus =='未连接'?'开始录像':'开始录像（有遥控器）'">
          <img  src="@/assets/detection/startvideo.png" alt="">
        </div>
        <div v-if="isStartVideo" class="icon-box" @click="stopVideoClick" title="结束录像">
          <img src="@/assets/detection/endvideo.png" alt="">
        </div>
        <div class="startvideo-box" v-if="isStartVideo">
          <img src="@/assets/detection/conduct.png" alt="" class="conductanimated">
          录像中: {{ formattedTime }}
        </div>
        <div class="startvideo-box" v-if="!isStartVideo">
        </div>
      </div>
      <div class="displayleft">
        <div class="icon-box" title="相机参数设置" @click="cameraUpdate">
          <img src="@/assets/detection/settings.png" alt="" >
        </div>
        <div class="icon-box" title="查看档案" @click="routerClick">
          <img src="@/assets/detection/archive.png" alt="" >
        </div>
      </div>
    </div>
    <div style="width:100%;height: calc(100% - 125px);" ref="contenGridRef">
      <!-- 主内容区域 -->
      <el-row :gutter="15" style="padding: 10px;padding-top:0" >
        <el-col :span="6" style="flex: 0 0 24%;height: calc(100% - 0px);">
          <div class="body-posture-box">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title1.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">身体姿态</div>
              </div>
              <div class="body-son-display">
                <img :src="femtoboltStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;"
                  @click="refreshClick('femtobolt')" title="重启深度相机">
                <div class="connecttext" :style="{ color: femtoboltStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ femtoboltStatus }}
                </div>
              </div>
            </div>
            <div ref="wholeBodyRef" style="display: flex;justify-content: center;height:calc( 100% - 50px);padding-top: 0px;"
              :style="{alignItems:(femtoboltStatus === '已连接' && depthCameraImgSrc)?'':'center'}">
              <img v-if="(femtoboltStatus === '已连接' && depthCameraImgSrc)" :src="depthCameraImgSrc" alt="深度相机视频流"
                style="width: 100%;height: calc(100%);">
                <!-- object-fit:contain; -->
              <div v-else style="width:90px;height:60px">
                <img :src="noImageSvg" style="margin-left: 15px;">
                <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
              </div>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="flex: 0 0 52%;max-width: 52%;height: calc(100% - 0px);">
          <!-- 头部姿态模块 -->
          <div class="body-header-box">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title2.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">头部姿态</div>
                <div class="calibration-zero" @click="calibrationClick" style="margin-left:20px">
                  <img src="@/assets/detection/calibration.png" style="margin-right:7px">
                  校准
                </div>
                <div class="calibration-zero" @click="clearAndStartTracking">
                  <img src="@/assets/detection/zero.png" style="margin-right:7px">
                  清零
                </div>
              </div>
              <div class="body-son-display">
                <img :src="imuStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;" title="重启IMU"
                @click="refreshClick('imu')">
                <div class="connecttext" :style="{ color: imuStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ imuStatus }}
                </div>
              </div>
            </div>
            <!--  头部姿态3D模型 -->
            <div class="body-header-bottombox" ref="imuHeaderRef">
              <div class="body-header-bottombox-left">
                <div class="body-header-bottombox-lefttext" style="height: 25%;"></div>
                <div class="body-header-bottombox-lefttext" >
                  <div class="currencytext1">左最大旋转角度</div>
                  <div class="currencytext2">{{
                    headPoseMaxValues.rotationLeftMax.toFixed(1) }}°</div>
                </div>
                <div class="body-header-bottombox-lefttext">
                  <div>
                    <div class="currencytext1">倾斜角</div>
                    <div class="currencytext2">{{ headlist.tilt }}°</div>
                  </div>
                  <div style="margin-top: 0px;">
                    <span>
                      <span class="currencytext4">左</span>
                      <span class="currencytext3">
                        {{ headPoseMaxValues.tiltLeftMax.toFixed(1) }}°
                      </span>
                    </span>
                    <span>|</span>
                    <span style="padding-left: 20px;">
                      <span class="currencytext4">右</span>
                      <span class="currencytext3">
                        {{ headPoseMaxValues.tiltRightMax.toFixed(1) }}°
                      </span>
                    </span>
                  </div>
                </div>
              </div>
              <div class="body-header-bottombox-content">
                <div style="text-align: center; width: 100%;" >
                  <span class="currencytext1">旋转角：</span>
                  <span class="currencytext2">{{ headlist.rotation }}°</span>
                </div>
                <div style="width: 100%;height: 80%;">
                  <Model :rotation="Number(headlist.rotation)" :tilt="Number(headlist.tilt)" :pitch="Number(headlist.pitch)*(-1)" :gender="patientInfo.gender || '男'" />
                </div>
               
              </div>
              <div class="body-header-bottombox-right">
                <div class="body-header-bottombox-righttext" style="height: 25%;"></div>
                <div class="body-header-bottombox-righttext" >
                  <div class="currencytext1">右最大旋转角度</div>
                  <div class="currencytext2">
                    {{ headPoseMaxValues.rotationRightMax.toFixed(1) }}°
                  </div>
                </div>
                <div class="body-header-bottombox-righttext">
                  <div>
                    <div class="currencytext1">俯仰角</div>
                    <div class="currencytext2">{{ headlist.pitch }}°</div>
                  </div>
                  <div style="margin-top: 0px;">
                    <span>
                      <span class="currencytext4">俯</span>
                      <span class="currencytext3">
                        {{  headPoseMaxValues.pitchDownMax.toFixed(1) }}°
                      </span>
                    </span>
                    <span>|</span>
                    <span style="padding-left: 20px;">
                      <span class="currencytext4">仰</span>
                      <span  style="text-align:right">
                        {{  headPoseMaxValues.pitchUpMax.toFixed(1) }}°
                      </span>
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="body-foot-box">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title3.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">足部压力</div>
              </div>
              <div class="body-son-display">
                <img :src="pressureStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;" title="重启足底压力板"
                @click="refreshClick('pressure')">
                <div class="connecttext" :style="{ color: pressureStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ pressureStatus }}
                </div>
              </div>
            </div>
            <div class="body-footbottom-box" ref="pressureRef">
              <div class="body-footbottom-left">
                <div style="width:100%;height: 50px;"></div>
                <div class="body-footbottom-leftbottom">
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">左前足</span>
                    <span class="currencytext2">
                      {{ footPressure.left_front }}%
                    </span>
                  </div>
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">左后足</span>
                    <span class="currencytext2">
                      {{ footPressure.left_rear }}%
                    </span>
                  </div>
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">左足总压力</span>
                    <span class="currencytext2">
                      {{ footPressure.left_total}}%
                    </span>
                  </div>
                </div>
              </div>
              <div class="body-footbottom-center">
                <div class="body-footbottom-topbox">
                  <div class="currencytext1" style="font-size:22px;text-align:center;">左足</div>
                  <div class="currencytext1" style="font-size:22px;text-align:center;">右足</div>
                </div>
                <div style="position: relative;width: 100%;height:calc(100% - 60px) ;" 
                :class="(pressureStatus === '已连接' && footImgSrc)?'':'noImageSvg-bg'">
                  
                  <img v-if="(pressureStatus === '已连接' && footImgSrc)"  :src="footImgSrc" style="width: 100%;height: 100%;" alt="">
                  <div v-else style="width:90px;height:60px">
                    <img :src="noImageSvg" style="margin-left: 15px;">
                    <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                  </div>
                  <div class="xline"></div>
                  <div class="yline"></div>
                </div>
              </div>
              <div class="body-footbottom-left">
                <div style="width:100%;height: 50px;"></div>
                <div class="body-footbottom-leftbottom">
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">右前足</span>
                    <span class="currencytext2">
                      {{ footPressure.right_front }}%
                    </span>
                  </div>
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">右后足</span>
                    <span class="currencytext2">
                      {{ footPressure.right_rear }}%
                    </span>
                  </div>
                  <div class="body-footbottom-leftbox">
                    <span class="currencytext1">右足总压力</span>
                    <span class="currencytext2">
                      {{ footPressure.right_total}}%
                    </span>
                  </div>
                </div>
              </div>

            </div>
          </div>
        </el-col>
        <el-col v-if=" camera1Status === '已连接' && camera2Status === '已连接' " 
         :span="6" style="flex: 0 0 24%;height: calc(100% - 0px); position: relative;">
          <div class="body-userinfo-box" :class="isExpand == true?'body-userinfo-expandbox':''">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title4.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">患者信息</div>
              </div>
              <div class="body-son-display"></div>
            </div>
            <div class="body-userinfo-content">
              <div class="body-userinfo-content-top">
                
                <img src="@/assets/detection/useredit.png" alt="" title="编辑患者信息"
                class="userinfo-edit-img" style="cursor: pointer;" @click="handleEditUserInfo">
                <div class="useravatar-box">
                  <img src="@/assets/detection/useravatar.svg" alt="">
                </div>
                <div>
                  <div class="userinfo-text-top">
                    <div class="userinfo-text1" style="margin-right:20px ;">{{ patientInfo.name }}</div>
                    <div class="userinfo-text2"> {{ patientInfo.gender }}</div>
                    <div class="userinfo-line"></div>
                    <div class="userinfo-text2">{{ calculateAge(patientInfo.birth_date) }}岁</div>
                  </div>
                  <div class="userinfo-text3">
                    ID：{{ patientInfo.id }}
                  </div>
                </div>

              </div>
              <div class="body-userinfo-content-bottom" v-if="isExpand == false">
                <img src="@/assets/detection/userinfo.png" alt=""
                class="userinfo-edit-img"   style="cursor: pointer;"
                  @click="viewClick(true)">
                <div class="userinfo-disyplay1" >
                  <div class="userinfo-text4">电话</div>
                  <div class="userinfo-text5">
                    <span  v-if="patientInfo && patientInfo.phone">
                      {{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}}
                    </span>
                  </div>
                </div>
                <div class="userinfo-disyplay2">
                  <div class="userinfo-text4">身高</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm
                  </div>
                </div>
                <div class="userinfo-disyplay1" style="padding-top: 20px;">
                  <div class="userinfo-text4">体重</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg
                  </div>
                </div>
                <div class="userinfo-disyplay2">
                  <div class="userinfo-text4">鞋码</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码</div>
                </div>
              
              </div>
              <div class="body-userinfo-content-bottom2" v-if="isExpand == true">
                <img src="@/assets/detection/userinfo.png" alt=""
                  class="userinfo-edit-img"   style="cursor: pointer;"
                    @click="viewClick(false)">
                <div class="userinfo-disyplaypadding1 ">
                  <div class="userinfo-text4 padding10">出生日期</div>
                  <div class="userinfo-text5">
                    <span  v-if="patientInfo && patientInfo.birth_date">
                      {{ formatDate(patientInfo.birth_date) }}
                    </span>
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">身高</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm
                  </div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">体重</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">鞋码</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码</div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">电话</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">民族</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.nationality ==''||patientInfo.nationality ==null ?'—':patientInfo.nationality}}</div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">身份证号</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.idcode ==''||patientInfo.idcode ==null ?'—':patientInfo.idcode}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">职业</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.occupation ==''||patientInfo.occupation ==null ?'—':patientInfo.occupation}}</div>
                </div>
                <div class="userinfo-disyplaypadding3">
                  <div class="userinfo-text4 padding10">居住地</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.residence ==''||patientInfo.residence ==null ?'—':patientInfo.residence}}</div>
                </div>
                <div class="userinfo-disyplaypadding3">
                  <div class="userinfo-text4 padding10">邮箱</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.email ==''||patientInfo.email ==null ?'—':patientInfo.email}}</div>
                </div>
               
              </div>
            </div>
          </div>
          <div class="body-video-box" style="position: absolute;top: 347px; width: calc(100% - 15px);">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title5.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">视频</div>
              </div>
              <div class="body-son-display">
                <img :src="cameraStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;"
                title="重启视频"
                @click="refreshClick('camera')">
                <div class="connecttext" :style="{ color: cameraStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ cameraStatus }}
                </div>
              </div>
            </div>
            <div class="body-video-content"> 
              <div class="body-video-imgbox1" ref="camera1Ref" :class="(camera1Status === '已连接' && camera1ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera1Status === '已连接' && camera1ImgSrc)" 
                @click="isBig1 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera1Status === '已连接' && camera1ImgSrc)" :src="camera1ImgSrc" alt="camera1"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
              <div class="body-video-imgbox2" ref="camera2Ref" :class="(camera2Status === '已连接' && camera2ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera2Status === '已连接' && camera2ImgSrc)" 
                @click="isBig2 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera2Status === '已连接' && camera2ImgSrc)"  :src="camera2ImgSrc" alt="camera2"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
            </div>
          </div>
        </el-col>


        <el-col v-if="camera1Status === '已连接' || camera2Status === '已连接'" 
         :span="6" style="flex: 0 0 24%;height: calc(100% - 0px);">
          <div class="body-userinfo-box1">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title4.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">患者信息</div>
              </div>
              <div class="body-son-display"></div>
            </div>
            <div class="body-userinfo-content">
              <div class="body-userinfo-content-top">
                
                <img src="@/assets/detection/useredit.png" alt="" title="编辑患者信息"
                class="userinfo-edit-img" style="cursor: pointer;" @click="handleEditUserInfo">
                <div class="useravatar-box">
                  <img src="@/assets/detection/useravatar.svg" alt="">
                </div>
                <div>
                  <div class="userinfo-text-top">
                    <div class="userinfo-text1" style="margin-right:20px ;">{{ patientInfo.name }}</div>
                    <div class="userinfo-text2"> {{ patientInfo.gender }}</div>
                    <div class="userinfo-line"></div>
                    <div class="userinfo-text2">{{ calculateAge(patientInfo.birth_date) }}岁</div>
                  </div>
                  <div class="userinfo-text3">
                    ID：{{ patientInfo.id }}
                  </div>
                </div>

              </div>
              <div class="body-userinfo-content-bottom1">
                <div class="userinfo-disyplaypadding4">
                  <div class="userinfo-text4">出生日期</div>
                  <div class="userinfo-text5">
                    <span  v-if="patientInfo && patientInfo.birth_date">
                  {{ formatDate(patientInfo.birth_date) }}
                  </span>
                  </div>
                </div>
                <div class="userinfo-disyplaypadding5">
                  <div class="userinfo-text4">身高</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm
                  </div>
                </div>
                <div class="userinfo-disyplaypadding4">
                  <div class="userinfo-text4">体重</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg
                  </div>
                </div>
                <div class="userinfo-disyplaypadding5">
                  <div class="userinfo-text4">鞋码</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码</div>
                </div>
                <div class="userinfo-disyplaypadding4">
                  <div class="userinfo-text4">电话</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding5">
                  <div class="userinfo-text4">民族</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.nationality ==''||patientInfo.nationality ==null ?'—':patientInfo.nationality}}</div>
                </div>
                <div class="userinfo-disyplaypadding4">
                  <div class="userinfo-text4">身份证号</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.idcode ==''||patientInfo.idcode ==null ?'—':patientInfo.idcode}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding5">
                  <div class="userinfo-text4">职业</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.occupation ==''||patientInfo.occupation ==null ?'—':patientInfo.occupation}}</div>
                </div>
                <div class="userinfo-disyplaypadding6">
                  <div class="userinfo-text4">居住地</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.residence ==''||patientInfo.residence ==null ?'—':patientInfo.residence}}</div>
                </div>
                <div class="userinfo-disyplaypadding6">
                  <div class="userinfo-text4">邮箱</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.email ==''||patientInfo.email ==null ?'—':patientInfo.email}}</div>
                </div>
               
              </div>
            </div>
          </div>
          <div class="body-video-box1">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title5.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">视频</div>
              </div>
              <div class="body-son-display">
                <img :src="cameraStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;"
                title="重启视频"
                @click="refreshClick('camera')">
                <div class="connecttext" :style="{ color: cameraStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ cameraStatus }}
                </div>
              </div>
            </div>
            <div class="body-video-content"> 
              <div v-show="camera1Status === '已连接'" class="body-video-imgbox3" ref="camera1Ref" :class="(camera1Status === '已连接' && camera1ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera1Status === '已连接' && camera1ImgSrc)" 
                @click="isBig1 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera1Status === '已连接' && camera1ImgSrc)" :src="camera1ImgSrc" alt="camera1"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
              <div v-show="camera2Status === '已连接'" class="body-video-imgbox3" ref="camera2Ref" :class="(camera2Status === '已连接' && camera2ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera2Status === '已连接' && camera2ImgSrc)" 
                @click="isBig2 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera2Status === '已连接' && camera2ImgSrc)"  :src="camera2ImgSrc" alt="camera2"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
            </div>
          </div>
        </el-col>
        <el-col v-if="camera1Status !== '已连接' && camera2Status !== '已连接'" :span="6" style="flex: 0 0 24%;height: calc(100% - 0px);">
          <div class="body-userinfo-box3">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title4.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">患者信息</div>
              </div>
              <div class="body-son-display"></div>
            </div>
            <div class="body-userinfo-content">
              <div class="body-userinfo-content-top">
                
                <img src="@/assets/detection/useredit.png" alt="" title="编辑患者信息"
                  class="userinfo-edit-img" style="cursor: pointer;" @click="handleEditUserInfo">
                <div class="useravatar-box">
                  <img src="@/assets/detection/useravatar.svg" alt="">
                </div>
                <div>
                  <div class="userinfo-text-top">
                    <div class="userinfo-text1" style="margin-right:20px ;">{{ patientInfo.name }}</div>
                    <div class="userinfo-text2"> {{ patientInfo.gender }}</div>
                    <div class="userinfo-line"></div>
                    <div class="userinfo-text2">{{ calculateAge(patientInfo.birth_date) }}岁</div>
                  </div>
                  <div class="userinfo-text3">
                    ID：{{ patientInfo.id }}
                  </div>
                </div>

              </div>
              <div class="body-userinfo-content-bottom0">
                <div class="userinfo-disyplaypadding1 ">
                  <div class="userinfo-text4 padding10">出生日期</div>
                  <div class="userinfo-text5">
                    <span  v-if="patientInfo && patientInfo.birth_date">
                  {{ formatDate(patientInfo.birth_date) }}
                  </span>
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">身高</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.height ==''||patientInfo.height ==null ?'—':patientInfo.height}}cm
                  </div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">体重</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.weight ==''||patientInfo.weight ==null ?'—':patientInfo.weight}}kg
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">鞋码</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.shoe_size ==''||patientInfo.shoe_size ==null ?'—':patientInfo.shoe_size}}码</div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">电话</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.phone ==''||patientInfo.phone ==null ?'—':patientInfo.phone}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">民族</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.nationality ==''||patientInfo.nationality ==null ?'—':patientInfo.nationality}}</div>
                </div>
                <div class="userinfo-disyplaypadding1">
                  <div class="userinfo-text4 padding10">身份证号</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.idcode ==''||patientInfo.idcode ==null ?'—':patientInfo.idcode}}
                  </div>
                </div>
                <div class="userinfo-disyplaypadding2">
                  <div class="userinfo-text4 padding10">职业</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.occupation ==''||patientInfo.occupation ==null ?'—':patientInfo.occupation}}</div>
                </div>
                <div class="userinfo-disyplaypadding3">
                  <div class="userinfo-text4 padding10">居住地</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.residence ==''||patientInfo.residence ==null ?'—':patientInfo.residence}}</div>
                </div>
                <div class="userinfo-disyplaypadding3">
                  <div class="userinfo-text4 padding10">邮箱</div>
                  <div class="userinfo-text5">
                    {{ patientInfo.email ==''||patientInfo.email ==null ?'—':patientInfo.email}}</div>
                </div>
               
              </div>
            </div>
          </div>
          <div v-show="false" class="body-video-box">
            <div class="body-title-display">
              <div class="body-son-display">
                <img src="@/assets/detection/title5.png" alt="" style="margin-right: 8px;">
                <div class="body-posture-text">视频</div>
              </div>
              <div class="body-son-display">
                <img :src="cameraStatus == '已连接'?refresh_active:refresh" alt="" style="margin-right: 8px;cursor: pointer;"
                title="重启视频"
                @click="refreshClick('camera')">
                <div class="connecttext" :style="{ color: cameraStatus == '已连接' ? '#3bf2c6' : '#808080' }">
                  {{ cameraStatus }}
                </div>
              </div>
            </div>
            <div class="body-video-content"> 
              <div class="body-video-imgbox1" ref="camera1Ref" :class="(camera1Status === '已连接' && camera1ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera1Status === '已连接' && camera1ImgSrc)" 
                @click="isBig1 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera1Status === '已连接' && camera1ImgSrc)" :src="camera1ImgSrc" alt="camera1"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
              <div class="body-video-imgbox2" ref="camera2Ref" :class="(camera2Status === '已连接' && camera2ImgSrc)?'':'noImageSvg-bg'"> 
                <div  v-if="(camera2Status === '已连接' && camera2ImgSrc)" 
                @click="isBig2 = true" class="big-img">
                  <img src="@/assets/detection/big.png">
                </div>
                <img v-if="(camera2Status === '已连接' && camera2ImgSrc)"  :src="camera2ImgSrc" alt="camera2"
                  style="width: 100%; height: 100%;" />
                <div v-else style="width:90px;height:60px">
                  <img :src="noImageSvg" style="margin-left: 15px;">
                  <div style="font-size:14px;color:#ffffff99;text-align: center;">连接已断开！</div>
                </div>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>
     <!-- 无操作退出提示 -->
    <div class="pop-up-mask" v-if="isTip">
      <div class="pop-up-tip-container">
        <div class="pop-up-tip-header">
            <div>提示</div>
            <img src="@/assets/header/closepage.png" alt="" style="cursor: pointer;" @click="handleCancel">
        </div>
        <div class="pop-up-tip-text" v-if="!isVideoOperation">本次检测未截图或录像操作，不予存档记录！</div>
        <div class="pop-up-tip-text" v-if="isVideoOperation">本次检测未截图操作，存档记录不可生成报告！</div>
        <div class="tipconfirmbutton-box">
          <el-button   type="primary" class="tipconfirmbutton" @click="closeTipClick">确定</el-button>         
        </div>
      </div>
    </div>

    <!-- 诊断信息 -->
    <div class="pop-up-mask" v-if="isDiagnosticMessage">
      <DiagnosticMessage @closeDiagnosticMessage="closeDiagnosticMessage"
       :selectedPatient="patientInfo" v-if="isDiagnosticMessage"/>
    </div>

    <div class="pop-up-mask" v-if="isCloseCreat">
      <PatientCreate @closecreatbox="closecreatbox" :patienttype="'edit'"
       :selectedPatient="selectedPatient" v-if="isCloseCreat"/>
    </div>
    <div class="pop-up-mask" v-if="cameraDialogVisible">
      <div class="pop-up-camera-container">
        <div class="pop-up-camera-header">
            <div>相机参数设置</div>
            <img src="@/assets/close.png" alt="" style="cursor: pointer;" @click="handleCameraCancel">
        </div>
        <div class="pop-up-camera-body">
          <div class="pop-up-camera-display">
            <div class="pop-up-camera-line"></div>
            <div class="pop-up-camera-title">深度相机</div>
          </div>
          <div class="pop-up-camera-display" style="padding-top: 10px;">
            <div class="pop-up-camera-name">距离范围</div>
            <el-input v-model="cameraForm.femtobolt.depth_range_min" placeholder="请输入最小值" 
            style="width: 200px;" />
            <div style="margin: 0 10px;">至</div>
            <el-input v-model="cameraForm.femtobolt.depth_range_max" placeholder="请输入最大值"  
            style="width: 200px;"/>
            <el-checkbox v-model="cameraForm.femtobolt.enable" label="有效" size="large" style="width: 60px;margin-left:10px ;" />

          </div>
          <div class="pop-up-camera-display" style="padding-top: 30px;padding-bottom: 10px;">
            <div class="pop-up-camera-line"></div>
            <div class="pop-up-camera-title">足部相机</div>
          </div>
          <div class="pop-up-camera-display" style="padding-top: 0px;">
            <div class="pop-up-camera-name">相机上</div>
            <el-radio-group v-model="cameraForm.camera1.device_index">
              <div style="display: flex;justify-content: space-between;width: 435px;">
                <el-radio :value="0" border>1号</el-radio>
                <el-radio :value="1" border>2号</el-radio>
                <el-radio :value="2" border>3号</el-radio>
                <el-radio :value="3" border>4号</el-radio>
                <el-radio :value="4" border>5号</el-radio>               
              </div>
            </el-radio-group>
            <el-checkbox v-model="cameraForm.camera1.enable" label="有效" size="large" style="width: 60px;margin-left:10px ;" />
          </div>
          <div class="pop-up-camera-display" style="padding-top: 20px;">
            <div class="pop-up-camera-name">相机下</div>
            <el-radio-group v-model="cameraForm.camera2.device_index">
              <div style="display: flex;justify-content: space-between;width: 435px;">
                 <el-radio :value="0" border>1号</el-radio>
                <el-radio :value="1" border>2号</el-radio>
                <el-radio :value="2" border>3号</el-radio>
                <el-radio :value="3" border>4号</el-radio>
                <el-radio :value="4" border>5号</el-radio> 
              </div>
            </el-radio-group>
            <el-checkbox v-model="cameraForm.camera2.enable" label="有效" size="large" style="width: 60px;margin-left:10px ;" />
          </div>
          <div class="pop-up-camera-display" style="padding-top: 30px;padding-bottom: 00px;">
            <div class="pop-up-camera-line"></div>
            <div class="pop-up-camera-title">遥控器</div>
          </div>
          <div class="pop-up-camera-display" style="padding-top: 10px;">
            <div class="pop-up-camera-name">串口号</div>
            <el-select v-model="cameraForm.remote.port" placeholder="请选择" style="width: 434px;">
              <el-option v-for="item in remotePortData" :label="item" :value="item" />
            </el-select>
            <el-checkbox v-model="cameraForm.remote.enable" label="有效" size="large" style="width: 60px;margin-left:10px ;" />

          </div>

          <div class="pop-up-camera-display" style="padding-top: 30px;padding-bottom: 00px;">
            <div class="pop-up-camera-line"></div>
            <div class="pop-up-camera-title">IMU设备</div>
          </div>
          <div class="pop-up-camera-display" style="padding-top: 10px;">
            <div class="pop-up-camera-name">Mac地址</div>
            <el-input v-model="cameraForm.imu.mac_address" placeholder="请输入" 
            style="width: 434px;" />
            <el-checkbox v-model="cameraForm.imu.enable" label="有效" size="large" style="width: 60px;margin-left:10px ;" />

          </div>
          
          <div class="form-actions-display">
            <el-button @click="handleCameraCancel" class="formreturnCancel">退出</el-button>
            <el-button type="primary" class="formsaveCancel"
            @click="cameraSubmit('cameraForm')">
                保存
              </el-button>
          </div>
      </div>
      </div>
    </div>
    <div class="pop-up-mask" v-if="isPhotoAlbum">
      <PhotoAlbum @closePhotoAlbum="closePhotoAlbum"
       :selectedPatient="patientInfo" v-if="isPhotoAlbum"/>
    </div>
    
    <PatientProfile v-if="historyDialogVisible" 
      :archiveType="true"
      :selectedPatient="selectedPatient"
      @closePatientProfile="closePatientProfile"/>

    <div v-if="isBig1" style="position: fixed;top: 122px;right: 0;
      width: 100%;height:calc(100% - 122px);z-index: 9999;
      background: linear-gradient(135deg, #1a1e2a 0%, #222b38 100%);
      border: 1px solid #262d40;">
      <svg @click="isBig1=false" style="position: absolute;right: 10px;top:10px;cursor: pointer;" t="1760175800150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5743" width="24" height="24"><path d="M796 163.1L511.1 448l-285-285-63.9 64 285 285-285 285 63.8 63.8 285-285 285 285 63.8-63.8-285-285 285-285-63.8-63.9z" fill="#ffffff" p-id="5744"></path></svg>
        <img v-if="isBig1" :src="camera1ImgSrc" alt=""
          style="width: 100%;height: calc(100%);object-fit:contain;background:#323232;" />
    </div>
    
    <div v-if="isBig2" style="position: fixed;top: 122px;right: 0;
      width: 100%;height:calc(100% - 122px);z-index: 9999;
      background: linear-gradient(135deg, #1a1e2a 0%, #222b38 100%);
      border: 1px solid #262d40;">
      <svg @click="isBig2=false" style="position: absolute;right: 10px;top:10px;cursor: pointer;" t="1760175800150" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5743" width="24" height="24"><path d="M796 163.1L511.1 448l-285-285-63.9 64 285 285-285 285 63.8 63.8 285-285 285 285 63.8-63.8-285-285 285-285-63.8-63.9z" fill="#ffffff" p-id="5744"></path></svg>
        <img v-if="isBig2" :src="camera2ImgSrc" alt=""
          style="width: 100%;height: calc(100%);object-fit:contain;background:#323232;" />
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter, useRoute } from 'vue-router'
import { io } from 'socket.io-client'
import Header from '@/views/Header.vue'
import { useAuthStore } from '../stores/index.js'
import * as echarts from 'echarts'
import { getBackendUrl, patientAPI } from '../services/api.js'
import noImageSvg from '@/assets/detection/no-image.png'
import DiagnosticMessage from '@/views/DiagnosticMessage.vue'
import PatientCreate from '@/views/PatientCreate.vue'
import PatientProfile from '@/views/PatientProfile.vue'
import Model from './model.vue'
import ViewUserInfo from '@/views/ViewUser.vue'
import PhotoAlbum from '@/views/PhotoAlbum.vue'

import refresh from '@/assets/detection/refresh.png'
import refresh_active from '@/assets/detection/refresh_active.png'
const emit = defineEmits([ 'endChange']);
const props = defineProps({
  selectedPatient: {
    required: false,
    type: Object,
    default: null
  },
})
const remotePortData =ref([]) // 遥控器串口数据
const videoNum = ref(2) // 视频数量
const videoTop = ref(1) //  视频位置
const isExpand = ref(false) // 是否展开
const isViewUser = ref(false) // 查看信息
const isCloseCreat =ref(false) // 是否打开患者信息编辑框
const isoperation = ref(false)  // 是否保存数据
const isVideoOperation = ref(false) // 是否录制视频
const isTip =ref(false)
const isStartVideo = ref(false)
function startVideoClick() {
  startRecord()
  isVideoOperation.value = true
  isStartVideo.value = true
}
function stopVideoClick() {
  stopRecord()
  isStartVideo.value = false
}
 function endClick() {
  if(isoperation.value == true){
    isDiagnosticMessage.value = true
  }else{
    isTip.value = true
  }
}
function handleCancel(){
  isTip.value = false
}
 function handleCameraCancel(){
  cameraDialogVisible.value = false
 }
async function closeTipClick(){
  try {
    if (timerId.value) {
      clearInterval(timerId.value)
      timerId.value = null
    }
    if (isRecording.value === true) {
      stopRecord()
    }
    await stopDetection({})
    disconnectWebSocket()
    window.removeEventListener('beforeunload', handleBeforeUnload)
    emit('endChange',false)
    routeTo('/')
  } catch (error) {
    emit('endChange',false)
  }
}

const isDiagnosticMessage = ref(false)

const isBig1 =ref(false)
const isBig2 =ref(false)
const authStore = useAuthStore()
const router = useRouter()
const isRecording = ref(false)
const isConnected = ref(false)
const rtspImgSrc = ref('')
const camera1ImgSrc = ref('')
const camera2ImgSrc = ref('')
const depthCameraImgSrc = ref('') // 深度相机视频流
const screenshotLoading = ref(false)
const cameraDialogVisible =ref(false) // 设置相机参数弹框
const contenGridRef =ref(null) // 实时检查整体box
const wholeBodyRef = ref(null) // 身体姿态ref
const camera1Ref = ref(null) // 视频1ref
const camera2Ref = ref(null) // 视频2ref
const pressureRef = ref(null) // 足底压力ref
const imuHeaderRef = ref(null) // IMUref
const historyDialogVisible = ref(false)
// 患者信息（从页面获取或通过API获取）
const patientInfo = ref({
  id: '',
  name: '',
  gender: '',
  birth_date: '',
  age: '',
  height: '',
  weight: '',
  shoe_size: '',
  phone: '',
  nationality: '',
  created_at: '',
  sessionId: null // 检查记录ID，实际使用时应从路由或API获取
})

// WebSocket相关变量
let socket = null
let devicesSocket = null
let cameraSocket = null
let femtoboltSocket = null
let imuSocket = null
let pressureSocket = null
let restartSocket = null
let frameCount = 0
let latestFrameCamera1 = ''
let latestFrameCamera2 = ''
let rafScheduled = false
let lastRenderTs = 0
const MAX_RENDER_FPS = 30

// 后端服务器地址配置
const BACKEND_URL = getBackendUrl()
const resDialogVisible = ref(false)
const dialogVisible = ref(false)
// 表单引用
const patientFormRef = ref()
// 表单数据
const saveLoading = ref(false)
const patientForm = ref({
  id: '',
  name: '',
  gender: '',
  birth_date: '',
  nationality: '',
  residence: '',
  height: '',
  weight: '',
  shoe_size: '',
  phone: '',
  occupation: '',
  workplace: '',
  email: ''
})
const occupationOptions = ref(["学生", "教师", "医生", "护士", "工程师", "程序员", "设计师", 
"会计师", "律师", "警察", "消防员", "军人", "公务员", "销售", "市场营销", 
"人力资源", "行政", "财务", "咨询师", "建筑师", "科研人员", "记者", "编辑", 
"作家", "艺术家", "音乐家", "演员", "导演", "摄影师", "厨师", "服务员", 
"司机", "快递员", "外卖员", "农民", "工人", "电工", "焊工", "机械师", 
"飞行员", "空乘", "船员", "导游", "翻译", "心理咨询师", "社会工作者", 
"运动员", "教练", "经纪人", "投资人", "企业家", "自由职业者"])
const nationalityOptions = ref(["汉族", "满族", "蒙古族", "回族", "藏族", "维吾尔族", "苗族", "彝族", "壮族", 
"布依族", "朝鲜族", "侗族", "瑶族", "白族", "土家族", "哈尼族", "哈萨克族", "傣族", 
"黎族", "傈僳族", "佤族", "畲族", "高山族", "拉祜族", "水族", "东乡族", "纳西族", 
"景颇族", "柯尔克孜族", "土族", "达斡尔族", "仫佬族", "羌族", "布朗族", "撒拉族", 
"毛南族", "仡佬族", "锡伯族", "阿昌族", "普米族", "塔吉克族", "怒族", "乌孜别克族", 
"俄罗斯族", "鄂温克族", "德昂族", "保安族", "裕固族", "京族", "塔塔尔族", "独龙族", 
"鄂伦春族", "赫哲族", "门巴族", "珞巴族", "基诺族"])
const diagnosticForm = ref({
  diagnosis_info: '',
  treatment_info: '',
  suggestion_info: ''
})
const cameraForm = ref({ // 相机参数
  camera1:{
    device_index: '',  // 序号
  },
  camera2:{
    device_index: '',  // 序号
  },
  femtobolt:{
    algorithm_type: '', // 算法类型
    depth_mode: '', // 相机模式
    depth_range_min: '', // 距离范围最小值
    depth_range_max: '', // 距离范围最大值
  },
  imu:{
    mac_address: '', // IMU串口号
    enable: false
  },
  remote:{
    port: '', // 遥控器串口号
    enable: false
  },

})
const calculatedAge = ref(null)
//修改

// 模拟历史数据
const historyData = ref([])
const chartoption = ref({
  backgroundColor: '#242424',
  grid: { top: 0, right: 0, bottom: 0, left: 0 },
  animation: false,
  series: [
    {
      type: 'gauge',
      radius: '180%',
      center: ['50%', '91%'],
      startAngle: 180,
      endAngle: 0,
      min: -90,
      max: 90,
      splitNumber: 10,
      itemStyle: {
        color: '#58D9F9',
        shadowColor: 'rgba(0,138,255,0.45)',
        shadowBlur: 10,
        shadowOffsetX: 2,
        shadowOffsetY: 2
      },
      progress: {
        show: false,
      },
      pointer: {
        length: '85%',
        width: 2,
        offsetCenter: [0, '5%'],
        itemStyle: {
          color: '#ff8d00'
        },
      },
      anchor: {
        show: true,
        showAbove: true,
        size: 18,
        icon: 'circle',
        itemStyle: {
          borderWidth: 3,
          color: '#ff8d00',
          borderColor: '#ff8d00',
        }
      },
      axisLine: {
        roundCap: true,
        lineStyle: {
          width: 3,
          color: [[1, '#0089ff']]
        }
      },
      axisTick: {
        splitNumber: 2,
        lineStyle: {
          width: 2,
          color: '#ffffff'
        }
      },
      splitLine: {
        length: 12,
        lineStyle: {
          width: 4,
          color: '#0089ff'
        }
      },
      axisLabel: {
        //刻度颜色
        distance: 10,
        color: '#ffffff',
        fontSize: 10
      },
      title: {
        show: false
      },
      detail: {
        show: false,
      },
      data: [
        {
          value: 0
        }
      ]
    }
  ]
})
// 四个设备的独立连接状态
const camera1Status = ref('未连接')
const camera2Status = ref('未连接')
const cameraStatus = computed(() => (camera1Status.value === '已连接' || camera2Status.value === '已连接') ? '已连接' : '未连接')
const femtoboltStatus = ref('未连接')     // 深度相机(FemtoBolt)设备状态
const imuStatus = ref('未连接')           // IMU设备状态
const pressureStatus = ref('未连接')      // 压力传感器设备状态
const remoteStatus = ref('未连接')      // 遥控器设备状态

// 为了向后兼容，保留videoStatus但映射到cameraStatus
const videoStatus = computed(() => cameraStatus.value)
// 计时器状态
const seconds = ref(0);
const isRunning = ref(false);
const timerId = ref(null);
const blinkState = ref(false);
const formattedTime = computed(() => {

  const mins = Math.floor(seconds.value / 60);
  const secs = seconds.value % 60;
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
});
const headlist = ref({
  rotation: 0,
  tilt: 0,
  pitch: 0
})
// 开始计时器
const startTimer = () => {
  if (isRunning.value) return;

  isRunning.value = true;
  seconds.value = 0;

  // 使用高性能计时器
  const startTime = Date.now();

  timerId.value = setInterval(() => {
    // 计算经过的时间（毫秒）
    const elapsed = Date.now() - startTime;
    // 转换为秒并四舍五入
    seconds.value = Math.round(elapsed / 1000);

    // 检测时长超过10分钟（1800秒）自动停止检测
    if (seconds.value >= 1800) {
      console.log('⏰ 检测时长超过30分钟，自动停止检测');
      ElMessage.warning('检测时长已达到30分钟，自动停止检测');
      stopRecord()
      return;
    }

    // 触发闪烁效果
    blinkState.value = !blinkState.value;
  }, 1000);
};
// 重置计时器
const resetTimer = () => {
  if (timerId.value) {
    clearInterval(timerId.value);
    timerId.value = null;
  }
  isRunning.value = false;
  seconds.value = 0;
  blinkState.value = false;
};
const validateForm = async () => {
  try {
    await patientFormRef.value.validate()
    return true
  } catch (error) {
    ElMessage.error('请完善必填信息')
    return false
  }
}
//保存基础信息
const handleSave = async () => {
  if (!(await validateForm())) return
  saveLoading.value = true
  try {
    await savePatient()
    ElMessage.success('修改成功')
    dialogVisible.value = false
    saveLoading.value = false
    loadPatientInfo()
  } catch (error) {
    ElMessage.error('修改失败：' + error.message)
    saveLoading.value = false
  } finally {
    saveLoading.value = false
  }
}
const savePatient = async () => {
  const patientData = {
    id: patientForm.value.id,
    name: patientForm.value.name,
    gender: patientForm.value.gender,
    age: calculatedAge.value,
    birth_date: patientForm.value.birth_date,
    height: patientForm.value.height,
    weight: patientForm.value.weight,
    shoe_size: patientForm.value.shoe_size,
    phone: patientForm.value.phone,
    occupation: patientForm.value.occupation,
    email: patientForm.value.email,
    nationality: patientForm.value.nationality,
    residence: patientForm.value.residence,
    workplace: patientForm.value.workplace
  }
  try {
    const response = await patientAPI.updatePatient(patientForm.value.id, patientData)
    if (response.success) {
      return response.data
    } else {
      throw new Error(response.message || '修改失败')
    }
  } catch (error) {
    throw error
  }
}
const isPreventCombo = ref(false)
function routeTo(path = '/') {
  if (isPreventCombo.value === true) {  
    ElMessage.warning(`请勿连续点击回退按钮！`)
    return
  }
  isPreventCombo.value = true
  setTimeout(() => {
    isPreventCombo.value = false
  }, 2000)
  router.push(path)
}
function cameraUpdate() {  // 相机设置数据更新弹框
  cameraForm.value = { // 相机参数
    camera1:{
      device_index: '',  // 序号1
    },
    camera2:{
      device_index: '',  // 序号2
    },
    femtobolt:{
      algorithm_type: '', // 算法类型
      depth_mode: '', // 相机模式
      depth_range_min: '', // 距离范围最小值
      depth_range_max: '', // 距离范围最大值
    },
    imu:{
      mac_address: '', // IMU串口号
      enable: false
    },
    remote:{
    port: '', // IMU串口号
  }
  }
  // 加载相机参数信息
  getDevicesInit()
 
}
const calculateAge = (birthDate) => {
  if (!birthDate) return '—'
  const today = new Date()
  const birth = new Date(birthDate)
  let age = today.getFullYear() - birth.getFullYear()
  const monthDiff = today.getMonth() - birth.getMonth()
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
    age--
  }
  return age
}
const tempInfo = ref({})
// WebSocket连接函数
function connectWebSocket() {
  try {
    console.log('正在连接到', BACKEND_URL)

    // 如果已有连接，先断开
    if (socket) {
      socket.disconnect()
      socket = null
    }
    if (cameraSocket) {
      cameraSocket.disconnect()
      cameraSocket = null
    }
    if (femtoboltSocket) {
      femtoboltSocket.disconnect()
      femtoboltSocket = null
    }
    if (imuSocket) {
      imuSocket.disconnect()
      imuSocket = null
    }
    if (pressureSocket) {
      pressureSocket.disconnect()
      pressureSocket = null
    }
    if (restartSocket) {
      restartSocket.disconnect()
      restartSocket = null
    }

    
    // 创建主Socket.IO连接
    socket = io(BACKEND_URL, {
      transports: ['websocket'],
      timeout: 10000,
      forceNew: true,
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000
    })

    // 创建统一设备命名空间连接
    devicesSocket = io(BACKEND_URL + '/devices', {
      transports: ['websocket'],
      timeout: 10000,
      forceNew: true
    })
    
    // 为了保持兼容性，将统一的设备socket赋值给各个设备变量
    cameraSocket = devicesSocket
    femtoboltSocket = devicesSocket
    imuSocket = devicesSocket
    pressureSocket = devicesSocket
    restartSocket = devicesSocket
    // 主连接事件
    socket.on('connect', () => {
      console.log('✅ 主WebSocket连接成功！Socket ID:', socket.id)
      isConnected.value = true
      //绘制头部仪表盘
      initchart()
    })

    socket.on('connect_error', (error) => {
      console.error('❌ 主连接失败:', error.message)
      isConnected.value = false      
    })

    socket.on('disconnect', (reason) => {
      console.log('⚠️ 主连接断开:', reason)
      isConnected.value = false      
    })

    socket.on('reconnect', (attemptNumber) => {
      console.log('🔄 主WebSocket重连成功，尝试次数:', attemptNumber)
      isConnected.value = true
    })

    socket.on('reconnect_attempt', (attemptNumber) => {
      console.log('🔄 正在尝试重连主连接...', attemptNumber)
    })

    socket.on('reconnect_failed', () => {
      console.error('❌ 主WebSocket重连失败')
      isConnected.value = false
    })



    socket.on('error', (error) => {
      console.error('❌ 主Socket错误:', error)
    })

    // 统一设备命名空间事件监听
    devicesSocket.on('connect', () => {
      console.log('🔗 设备命名空间连接成功')
      
      const enabledCameras = (() => {
        const list = []
        const idx1 = String((cameraForm.value && cameraForm.value.camera1 && cameraForm.value.camera1.device_index) || '').trim()
        const idx2 = String((cameraForm.value && cameraForm.value.camera2 && cameraForm.value.camera2.device_index) || '').trim()
        if (idx1 !== '') list.push('camera1')
        if (idx2 !== '') list.push('camera2')
        if (list.length === 0) list.push('camera1')
        return list
      })()
      enabledCameras.forEach(t => devicesSocket.emit('subscribe_device', { device_type: t }))
      devicesSocket.emit('subscribe_device', { device_type: 'femtobolt' })
      devicesSocket.emit('subscribe_device', { device_type: 'imu' })
      devicesSocket.emit('subscribe_device', { device_type: 'pressure' })
      devicesSocket.emit('subscribe_device', { device_type: 'remote' })
      
      // 设备连接成功后启动数据推送
      startDeviceDataPush()
    })
    
    devicesSocket.on('disconnect', () => {
      console.log('🔗 设备命名空间断开连接')
      // 断开连接时重置所有设备状态
      camera1Status.value = '未连接'
      camera2Status.value = '未连接'
      femtoboltStatus.value = '未连接'
      imuStatus.value = '未连接'
      pressureStatus.value = '未连接'
    })
    
    devicesSocket.on('connect_error', (error) => {
      console.error('❌ 设备命名空间连接失败:', error.message)
    })
    
     // 监听设备重启消息事件
    devicesSocket.on('device_restart_message', (data) => {   
      ElMessage.success({
      message: data.message,
      duration: 1000
    })         
    })

    // 监听各设备数据事件
    devicesSocket.on('camera_frame', (data) => {
      frameCount++
      // 区分 camera1 / camera2 帧
      const devId = (data && data.device_id) ? String(data.device_id).toLowerCase() : ''
     if (!tempInfo.value.camera_frames) {
       tempInfo.value.camera_frames = {}
     }
      if (devId === 'camera1') {
        tempInfo.value.camera_frames['camera1'] = data
        tempInfo.value.camera1_frame = data
        displayCameraFrameById('camera1', data.image)
      } else if (devId === 'camera2')  {       
        tempInfo.value.camera_frames['camera2'] = data
        tempInfo.value.camera2_frame = data
        displayCameraFrameById('camera2', data.image)
      }
    })  

    devicesSocket.on('femtobolt_frame', (data) => {
      tempInfo.value.femtobolt_frame = data
      displayDepthCameraFrame(data.depth_image || data.image)
    })    
    
    devicesSocket.on('imu_data', (data) => {
      tempInfo.value.imu_data = data
      handleIMUData(data)
    })
    
    devicesSocket.on('pressure_data', (data) => {
       tempInfo.value.pressure_data = data
       handlePressureData(data)
     })
    
    // 监听遥控器事件：根据编码触发页面方法
    devicesSocket.on('remote_control', (data) => {
      const code = String((data && data.code) || '').toUpperCase()
      switch (code) {
        case '11':
          startVideoClick()
          break
        case '14':
          stopVideoClick()
          break
        case '12':
          clearAndStartTracking()
          break
        case '0F':
          saveDetectionData()
          break
        default:
          break
      }
    })
     
     // 监听测试状态事件
     devicesSocket.on('test_status', (data) => {
       console.log('📊 测试状态:', data)
       if (data.status === 'started') {
         console.log('✅ 设备数据推送已开始')
       } else if (data.status === 'stopped') {
         console.log('⏹️ 设备数据推送已停止')
       } else if (data.status === 'error') {
         console.error('❌ 设备数据推送错误:', data.message)
       }
     })
     
     // 监听各设备独立连接状态事件
     devicesSocket.on('device_status', (data) => {
       console.log('📱 设备状态更新:', data)
       const { device_type, status } = data
       const statusText = status ? '已连接' : '未连接'
       
      switch (device_type) {
        case 'camera1':
          camera1Status.value = statusText
          console.log(`📷 相机1状态: ${statusText}`)
          break
        case 'camera2':
          camera2Status.value = statusText
          console.log(`📷 相机2状态: ${statusText}`)
          break
         case 'femtobolt':
           femtoboltStatus.value = statusText
           console.log(`🔍 深度相机状态: ${statusText}`)
           break
         case 'imu':
           imuStatus.value = statusText
           console.log(`🧭 IMU状态: ${statusText}`)
           break
         case 'pressure':
           pressureStatus.value = statusText
           console.log(`⚖️ 压力传感器状态: ${statusText}`)
           break
          case 'remote':
          remoteStatus.value = statusText
          console.log(`📡 遥控器状态: ${statusText}`)
          break
         default:
           console.warn('⚠️ 未知设备类型:', device_type)
       }
     })

  } catch (error) {
    console.error('💥 连接异常:', error.message)
    isConnected.value = false
  }
}

// 启动设备数据推送
function startDeviceDataPush() {
  if (devicesSocket && devicesSocket.connected) {
    console.log('🚀 发送启动设备数据推送请求...')
    devicesSocket.emit('start_push_data')
  } else {
    console.warn('⚠️ 设备Socket未连接，无法启动设备数据推送')
  }
}

// 断开WebSocket连接函数
function disconnectWebSocket() {
  try {
    if (socket) {
      if (socket.connected) {
        console.log('正在主动断开WebSocket连接...')
        
        // 移除所有事件监听器
        socket.removeAllListeners()
        
        // 断开主连接
        socket.disconnect()
        
        console.log('✅ 主WebSocket连接已断开')
      }
      socket = null
      isConnected.value = false
    }
    
    // 断开统一设备命名空间连接
    if (devicesSocket) {
      if (devicesSocket.connected) {
        // 取消订阅所有设备
        // try {
        //   devicesSocket.emit('unsubscribe_device', { device_type: 'camera1' })
        //   devicesSocket.emit('unsubscribe_device', { device_type: 'camera2' })
        //   devicesSocket.emit('unsubscribe_device', { device_type: 'femtobolt' })
        //   devicesSocket.emit('unsubscribe_device', { device_type: 'imu' })
        //   devicesSocket.emit('unsubscribe_device', { device_type: 'pressure' })
        // } catch (e) {
        //   console.warn('取消设备订阅时出错:', e)
        // }
        
        // 移除所有事件监听器
        devicesSocket.removeAllListeners()
        
        // 断开连接
        devicesSocket.disconnect()
        
        console.log('🔗 统一设备命名空间连接已断开')
      }
      
      devicesSocket = null
      cameraSocket = null
      femtoboltSocket = null
      imuSocket = null
      pressureSocket = null
      restartSocket = null
    }
    
    // 重置所有设备状态
    camera1Status.value = '未连接'
    camera2Status.value = '未连接'
    femtoboltStatus.value = '未连接'
    imuStatus.value = '未连接'
    pressureStatus.value = '未连接'
    
  } catch (error) {
    console.warn('断开WebSocket连接时出错:', error)
  }
}

// WebSocket重连函数
function reconnectWebSocket() {
  console.log('开始重新连接WebSocket...')
  
  // 先断开现有连接
  disconnectWebSocket()
  
  // 延迟一段时间后重新连接
  setTimeout(() => {
    connectWebSocket()
    console.log('WebSocket重连完成')
  }, 1000)
}




// 简单的帧显示函数
function displayFrame(base64Image) {
  // 兼容旧调用：默认作为 camera1 更新
  displayCameraFrameById('camera1', base64Image)
}

function displayCameraFrameById(deviceId, base64Image) {
  if (base64Image && base64Image.length > 0) {
    if (String(deviceId).toLowerCase() === 'camera2') {
      latestFrameCamera2 = base64Image
    } else {
      latestFrameCamera1 = base64Image
    }
    if (!rafScheduled) {
      rafScheduled = true
      requestAnimationFrame(() => {
        const now = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now()
        const minInterval = 1000 / MAX_RENDER_FPS
        if (now - lastRenderTs >= minInterval) {
          if (latestFrameCamera1) {
            const url1 = 'data:image/jpeg;base64,' + latestFrameCamera1
            camera1ImgSrc.value = url1
            rtspImgSrc.value = url1
          }
          if (latestFrameCamera2) {
            const url2 = 'data:image/jpeg;base64,' + latestFrameCamera2
            camera2ImgSrc.value = url2
          }
          lastRenderTs = now
        }
        rafScheduled = false
      })
    }
  } else {
    console.warn('⚠️ 收到空的视频帧数据')
  }
}

// 深度相机帧显示函数
function displayDepthCameraFrame(base64Image) {
  if (base64Image && base64Image.length > 0) {
    depthCameraImgSrc.value = 'data:image/jpeg;base64,' + base64Image
  } else {
    console.warn('⚠️ 收到空的深度相机帧数据')
  }
}


// 头部姿态最值跟踪数据
const headPoseMaxValues = ref({
  rotationLeftMax: 0,    // 旋转-左旋最大值
  rotationRightMax: 0,   // 旋转-右旋最大值
  tiltLeftMax: 0,        // 倾斜-左倾最大值
  tiltRightMax: 0,       // 倾斜-右倾最大值
  pitchUpMax: 0,         // 俯仰-上仰最大值
  pitchDownMax: 0        // 俯仰-下俯最大值
})

// 头部姿态历史最值记录数组
const headPoseHistory = ref([])
const headPoseData = ref({})

// IMU更新节流与抖动阈值（降低频繁DOM与图表更新导致的卡顿）
let lastIMUUpdateTs = 0
const IMU_MIN_INTERVAL_MS = 33 // 约30Hz
let lastIMUValues = { rotation: null, tilt: null, pitch: null }
const IMU_CHANGE_EPS = 0.1 // 小于0.1°的变化忽略


// 处理IMU头部姿态数据
function handleIMUData(data) {
  try {
    if (!data) return
  
    // 兼容两种载荷结构：
    // 1) { rotation, tilt, pitch }
    // 2) { head_pose: { rotation, tilt, pitch } }
    const rotation = (data.rotation ?? (data.head_pose && data.head_pose.rotation))
    const tilt = (data.tilt ?? (data.head_pose && data.head_pose.tilt))
    const pitch = (data.pitch ?? (data.head_pose && data.head_pose.pitch))

    if (rotation === undefined || tilt === undefined || pitch === undefined) {
      return
    }
    headlist.value.rotation = rotation // 旋转角度
    headlist.value.tilt = tilt // 倾斜角度
    headlist.value.pitch = pitch // 俯仰角度
    const now = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now()

    // 若距离上次更新时间很短且变化不明显，则跳过避免频繁DOM更新
    const tooSoon = (now - lastIMUUpdateTs) < IMU_MIN_INTERVAL_MS
    const notSignificant = (
      lastIMUValues.rotation !== null && Math.abs(rotation - lastIMUValues.rotation) < IMU_CHANGE_EPS &&
      lastIMUValues.tilt !== null && Math.abs(tilt - lastIMUValues.tilt) < IMU_CHANGE_EPS &&
      lastIMUValues.pitch !== null && Math.abs(pitch - lastIMUValues.pitch) < IMU_CHANGE_EPS
    )
    if (tooSoon && notSignificant) return

    lastIMUUpdateTs = now
    lastIMUValues = { rotation, tilt, pitch }

    const rVal = Math.round(rotation * 10) / 10
    const pVal = Math.round(pitch * 10) / 10
    const tVal = Math.round(tilt * 10) / 10

    if (rotationCharts && !rotationCharts.isDisposed()) {
      try {
        rotationCharts.setOption({
          series: [{ data: [{ value: rVal }] }]
        })
      } catch (e) {
        console.warn('rotationCharts setOption error:', e);
      }
    }
    if (pitchCharts && !pitchCharts.isDisposed()) {
      try {
        pitchCharts.setOption({
          series: [{ data: [{ value: pVal }] }]
        })
      } catch (e) {
        console.warn('pitchCharts setOption error:', e);
      }
    }
    if (tiltCharts && !tiltCharts.isDisposed()) {
      try {
        tiltCharts.setOption({
          series: [{ data: [{ value: tVal }] }]
        })
      } catch (e) {
        console.warn('tiltCharts setOption error:', e);
      }
    }

    // 更新最值跟踪逻辑使用原始数值（不做四舍五入）
    updateHeadPoseMaxValues({ rotation, tilt, pitch })
  } catch (error) {
    console.error('❌ 处理IMU数据失败:', error)
  }
}

// 更新头部姿态最值
function updateHeadPoseMaxValues(headPose) {
  try {
    // 更新旋转角最值
    if (headPose.rotation > 0) {
      // 左旋（负值），取绝对值的最大值
      headPoseMaxValues.value.rotationLeftMax = Math.max(
        headPoseMaxValues.value.rotationLeftMax,
        headPose.rotation
      )
    } else if (headPose.rotation < 0) {
      // 右旋（正值）
      headPoseMaxValues.value.rotationRightMax = Math.max(
        headPoseMaxValues.value.rotationRightMax,
        Math.abs(headPose.rotation)
        
      )
    }

    // 更新倾斜角最值
    if (headPose.tilt > 0) {
      // 左倾（负值），取绝对值的最大值
      headPoseMaxValues.value.tiltLeftMax = Math.max(
        headPoseMaxValues.value.tiltLeftMax,
         headPose.tilt
        
      )
    } else if (headPose.tilt < 0) {
      // 右倾（正值）
      headPoseMaxValues.value.tiltRightMax = Math.max(
        headPoseMaxValues.value.tiltRightMax,
       Math.abs(headPose.tilt)
      )
    }

    // 更新俯仰角最值
    if (headPose.pitch >0) {
      // 下俯（负值），取绝对值的最大值
      headPoseMaxValues.value.pitchDownMax = Math.max(
        headPoseMaxValues.value.pitchDownMax,
        headPose.pitch
        
      )
    } else if (headPose.pitch < 0) {
      // 上仰（正值）
      headPoseMaxValues.value.pitchUpMax = Math.max(
        headPoseMaxValues.value.pitchUpMax,
        Math.abs(headPose.pitch)
      )
    }

  } catch (error) {
    console.error('❌ 更新头部姿态最值失败:', error)
  }
}

// 清零最值并开始跟踪
function clearAndStartTracking() {
  try {
    // 重置所有最值为0
    headPoseMaxValues.value = {
      rotationLeftMax: 0,
      rotationRightMax: 0,
      tiltLeftMax: 0,
      tiltRightMax: 0,
      pitchUpMax: 0,
      pitchDownMax: 0
    }
  } catch (error) {
    ElMessage.error('清零失败')
  }
}

// 保存当前最值到历史记录
function saveMaxValuesToHistory() {
  try {
    // 创建当前最值的副本
    const currentMaxValues = {
      id: headPoseHistory.value.length + 1,
      rotationLeftMax: Number(headPoseMaxValues.value.rotationLeftMax.toFixed(1)),
      rotationRightMax: Number(headPoseMaxValues.value.rotationRightMax.toFixed(1)),
      tiltLeftMax: Number(headPoseMaxValues.value.tiltLeftMax.toFixed(1)),
      tiltRightMax: Number(headPoseMaxValues.value.tiltRightMax.toFixed(1)),
      pitchUpMax: Number(headPoseMaxValues.value.pitchUpMax.toFixed(1)),
      pitchDownMax: Number(headPoseMaxValues.value.pitchDownMax.toFixed(1)),
      timestamp: new Date().toLocaleString()
    }

    // 添加到历史记录
    headPoseHistory.value.push(currentMaxValues)


    // console.log('💾 头部姿态最值已保存:', currentMaxValues)
    // ElMessage.success(`头部姿态最值已保存（第${currentMaxValues.id}组）`)

    // 更新历史数据表格（如果存在的话）
    updateHistoryTable()
  } catch (error) {
    // console.error('❌ 保存最值失败:', error)
    ElMessage.error('保存最值失败')
  }
}

// 更新历史数据表格
function updateHistoryTable() {
  try {
    // 将头部姿态最值数据合并到现有的历史数据中
    if (headPoseHistory.value.length > 0) {
      const latestData = headPoseHistory.value[headPoseHistory.value.length - 1]

      // 更新historyData数组，添加头部姿态最值数据
      const newHistoryItem = {
        id: latestData.id,
        rotLeft: latestData.rotationLeftMax,
        rotRight: latestData.rotationRightMax,
        tiltLeft: latestData.tiltLeftMax,
        tiltRight: latestData.tiltRightMax,
        pitchDown: latestData.pitchDownMax,
        pitchUp: latestData.pitchUpMax,
        timestamp: latestData.timestamp
      }
      // 如果historyData数组存在，则添加新数据
      if (historyData.value) {
        historyData.value.push(newHistoryItem)
      }
      historyData.value.sort((a, b) => b.id - a.id);
      console.log('📋 历史数据表格已更新')
    }
  } catch (error) {
    console.error('❌ 更新历史数据表格失败:', error)
  }
}
const footPressure = ref({
  left_front: '',
  left_rear: '',
  right_front: '',
  right_rear: '',
  left_total: '',
  right_total: '',
  total_pressure: ''
})
const footImgSrc = ref('')
// 处理压力传感器足部压力数据
function handlePressureData(data) {
  try {
    if (data && data.foot_pressure) {
      const pressureData = data.foot_pressure

      // 更新足部压力数据
      // 显示分区压力值
      if (pressureData.pressure_zones) {
        footPressure.value = pressureData.pressure_zones
      }
   

      // 处理压力图片
      if (pressureData.pressure_image) {
        // console.log('  📊 接收到压力分布图片 (base64格式)')
        // 这里可以将图片显示在界面上
        if (pressureData.pressure_image && pressureData.pressure_image.length > 0) {
          footImgSrc.value = pressureData.pressure_image
        } else {
          console.warn('⚠️ 收到空的压力传感器数据图')
        }
      }
    }
  } catch (error) {
    console.error('❌ 处理压力传感器数据失败:', error)
  }
}




// 保存检测数据
async function saveDetectionData() {
  if (screenshotLoading.value) return
  let titile_height = 24
  try {
    screenshotLoading.value = true
    // 检查是否有活跃的会话ID
    if (!patientInfo.value.sessionId) {
      throw new Error('请先开始检测再进行数据保存')
    }
    const base64 = 'data:image/jpeg;base64,'
   
    let body_image = ""
    if(tempInfo.value.femtobolt_frame != null 
    && tempInfo.value.femtobolt_frame.depth_image != null){
      body_image = base64 + tempInfo.value.femtobolt_frame.depth_image       
    }

    let pressure_image = ""
    let foot_data = ""
    if(tempInfo.value.pressure_data != null 
    && tempInfo.value.pressure_data.foot_pressure != null
    && tempInfo.value.pressure_data.foot_pressure.pressure_image != null){
      pressure_image = tempInfo.value.pressure_data.foot_pressure.pressure_image 
      foot_data = tempInfo.value.pressure_data.foot_pressure.pressure_zones
    }

    let pressureBox =  pressureRef.value?.getBoundingClientRect()
    let imuHeaderBox =  imuHeaderRef.value?.getBoundingClientRect()
    
    let titile_height = 24
    pressure_image =[
      Math.round(pressureBox.x), Math.round(pressureBox.y)+ titile_height,
      Math.round(pressureBox.width), Math.round(pressureBox.height)
    ]
    let head_data_image = []
    head_data_image =[
      Math.round(imuHeaderBox.x), Math.round(imuHeaderBox.y)+ titile_height,
      Math.round(imuHeaderBox.width), Math.round(imuHeaderBox.height)
    ]
    let foot1_image=""
    if(tempInfo.value.camera1_frame != null 
    && tempInfo.value.camera1_frame.image != null ){
      foot1_image=base64 + tempInfo.value.camera1_frame.image
    }
    let foot2_image=""
    if(tempInfo.value.camera2_frame != null 
    && tempInfo.value.camera2_frame.image != null ){
      foot2_image=base64 + tempInfo.value.camera2_frame.image
    }


    let head_pose={}
    if(tempInfo.value.imu_data != null ){
      head_pose=tempInfo.value.imu_data
    }
    if(headPoseMaxValues !=null){
      head_pose.headPoseMaxValues = headPoseMaxValues.value
    }
    let screen_location = contenGridRef.value.getBoundingClientRect()
    // 调用后端API保存截图
    const result = await sendDetectionData({     

      session_id: patientInfo.value.sessionId,
      patient_id: patientInfo.value.id,
      screen_location:[Math.round(screen_location.x), Math.round(screen_location.y) + titile_height, Math.round(screen_location.width), Math.round(screen_location.height)],
      head_pose:head_pose,
      body_pose:null,
      body_image: body_image,

      foot_data:foot_data,
      foot1_image:foot1_image,
      foot2_image:foot2_image,
      foot_data_image:pressure_image,  
      head_data_image:head_data_image,   
      screen_image:null
 
    })    
    isoperation.value = true
    // 显示成功消息和文件路径
    ElMessage.success({
      message: `检测数据保存成功！`,
      duration: 500
    })


  } catch (error) {
    console.error('❌ 检测数据保存失败:', error)

    // 根据错误类型显示不同的错误消息
    let errorMessage = '检测数据保存失败'
    if (error.message.includes('网络连接失败')) {
      errorMessage = '网络连接失败，请检查后端服务是否正常运行'
    } else if (error.message.includes('服务器错误')) {
      errorMessage = error.message
    } else if (error.message.includes('未找到检测数据区域')) {
      errorMessage = '检测数据区域不存在，请刷新页面重试'
    } else if (error.message.includes('未找到检测数据')) {
      errorMessage = '检测数据不存在，请刷新页面重试'
    } else {
      errorMessage = `检测数据保存失败: ${error.message}`
    }

    ElMessage.error({
      message: errorMessage,
      duration: 5000
    })

  } finally {
    screenshotLoading.value = false
  }
}

// 调用后端API保存检测数据
async function sendDetectionData(data) {
  try {
    const response = await fetch(`${BACKEND_URL}/api/detection/${patientInfo.value.sessionId}/save-data`
      , {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      })

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }

    const result = await response.json()

    if (result.success) {
      console.log('📸 截图保存成功:', result.filepath)
      return result
    } else {
      throw new Error(result.message || '保存失败')
    }

  } catch (error) {
    console.error('💥 保存截图API调用失败:', error)

    if (error.name === 'TypeError' && error.message.includes('fetch')) {
      throw new Error('网络连接失败，请检查后端服务是否正常运行')
    } else if (error.message.includes('HTTP')) {
      throw new Error(`服务器错误: ${error.message}`)
    } else {
      throw new Error(error.message)
    }
  }
}

// 处理开始/停止按钮点击
// async function handleStartStop() {
//   if (isRecording.value) {
//     // 停止录制视频
//     await stopRecord()
//   } else {    
//     // 开始录制视频
//     await startRecord()
//   }
// }
// 开始检测
async function startDetection() {
  try {
    console.log('🚀 正在开始检测...')      
   
    // 调用后端API开始检测
    const response = await fetch(`${BACKEND_URL}/api/detection/start`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        patient_id: patientId.value,
        // 可以添加其他检测参数
        creator_id: creatorId.value,        
      })
    })
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }
    const result = await response.json()
    if (result.success) {
      console.log('✅ 检测开始成功')
      // 保存会话ID和检测开始时间
      patientInfo.value.sessionId = result.session_id
    } else {
      throw new Error(result.message || '开始检测失败')
    }

  } catch (error) {
    console.error('💥 开始检测失败:', error)
    ElMessage.error(`开始检测失败: ${error.message}`)
    throw error
  }
}

// 停止检测
async function stopDetection(summary = {}) {
  try {
    const payload = summary || {}
    const response = await fetch(`${BACKEND_URL}/api/detection/${patientInfo.value.sessionId}/stop`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    })
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }    
  } catch (error) {
    console.error('❌ 停止检测失败:', error)
    ElMessage.error(`停止检测失败: ${error.message}`)
  }
}
// 格式化日期方法
const formatDate = (dateString) => {
  if (!dateString) return '-'
  const date = new Date(dateString)
  return date.toLocaleDateString('zh-CN')
}
const patientId = ref("")

// 加载患者信息
const loadPatientInfo = async () => {
  try {
    // 从路由参数获取患者ID

    if (patientId.value == '' || patientId.value == null) {
      console.warn('未找到患者ID参数')
      return
    }
    // 调用API获取患者信息
    const response = await fetch(`${BACKEND_URL}/api/patients/${patientId.value}`)
    if (response.ok) {
      const result = await response.json()
      if (result.success) {
        patientInfo.value = { ...result.data, sessionId: null }
       
        console.log('患者信息加载成功:', patientInfo.value)
      } else {
        throw new Error(result.message)
      }
    } else {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }
  } catch (error) {
    console.error('加载患者信息失败:', error)
    ElMessage.warning('加载患者信息失败，请检查网络连接')
  }
}

// 处理页面关闭或刷新事件
const handleBeforeUnload = (event) => {
  console.log('页面即将关闭，正在清理资源...') 
  // 断开WebSocket连接
  disconnectWebSocket()
  
  console.log('✅ 资源清理完成')
}
const creatorId = ref('')
let rotationCharts = null;
let pitchCharts = null;
let tiltCharts = null;
const initchart = () => {
  // 确保 DOM 元素已经渲染
  nextTick(() => {
    const chartDom = document.getElementById('rotationChartId');
    if (chartDom) {
      // 如果图表已经存在，先销毁
      if (rotationCharts) {
        try {
          rotationCharts.dispose();
        } catch (e) {
          console.warn('rotationCharts dispose error:', e);
        }
        rotationCharts = null;
      }
      rotationCharts = echarts.init(chartDom);
      rotationCharts.setOption(chartoption.value);
    } else {
      console.warn('找不到 ID 为 rotationChartId 的 DOM 元素');
    }
    const chartDom2 = document.getElementById('pitchChartId');
    if (chartDom2) {
      // 如果图表已经存在，先销毁
      if (pitchCharts) {
        try {
          pitchCharts.dispose();
        } catch (e) {
          console.warn('pitchCharts dispose error:', e);
        }
        pitchCharts = null;
      }
      pitchCharts = echarts.init(chartDom2);
      pitchCharts.setOption(chartoption.value);
    } else {
      console.warn('找不到 ID 为 pitchChartId 的 DOM 元素');
    }
    const chartDom3 = document.getElementById('tiltChartId');
    if (chartDom3) {
      // 如果图表已经存在，先销毁
      if (tiltCharts) {
        try {
          tiltCharts.dispose();
        } catch (e) {
          console.warn('tiltCharts dispose error:', e);
        }
        tiltCharts = null;
      }
      tiltCharts = echarts.init(chartDom3);
      tiltCharts.setOption(chartoption.value);
    } else {
      console.warn('找不到 ID 为 tiltChartId 的 DOM 元素');
    }
    // 添加窗口大小调整监听器
    window.addEventListener('resize', () => {
      if (rotationCharts && !rotationCharts.isDisposed()) {
        try {
          rotationCharts.resize();
        } catch (e) {
          console.warn('rotationCharts resize error:', e);
        }
      }
      if (pitchCharts && !pitchCharts.isDisposed()) {
        try {
          pitchCharts.resize();
        } catch (e) {
          console.warn('pitchCharts resize error:', e);
        }
      }
      if (tiltCharts && !tiltCharts.isDisposed()) {
        try {
          tiltCharts.resize();
        } catch (e) {
          console.warn('tiltCharts resize error:', e);
        }
      }
    });
  });
}
const calibrationClick = async () => {
  const response = await fetch(`${BACKEND_URL}/api/devices/calibrate/imu`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({})
  })
  clearAndStartTracking()
  if (response.ok) {
    const result = await response.json()
    if (result.success) {
      ElMessage.success(result.message)
    } else {
      ElMessage.error(result.message)
    }
  }

}

const cameraSubmit = async () => {
  if(cameraForm.value.camera1.device_index == cameraForm.value.camera2.device_index){
    ElMessage.error('相机上和相机下的号码不能相同！')
    return
  }
  const response = await fetch(`${BACKEND_URL}/api/config/devices/all`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(cameraForm.value)
  })
  if (response.ok) {
    const result = await response.json()
    if (result.success) {
      ElMessage.success(result.message)
      cameraDialogVisible.value = false
    } else {
      ElMessage.error(result.message)
    }
  }else {
    const result = await response.json()
    ElMessage.error(result.message)
  }
}

// 加载相机参数信息
const getDevicesInit = async () => {
  try {
    // 调用API获取患者信息
    const response = await fetch(`${BACKEND_URL}/api/config/devices`)
    if (response.ok) {
      const result = await response.json()
      if (result.success) {
        console.log('相机参数加载成功:', result.data)
        cameraForm.value = result.data
        cameraDialogVisible.value = true
        // console.log('相机参数加载成功:', patientInfo.value)
      } else {
        throw new Error(result.message)
      }
    } else {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }
  } catch (error) {
    console.error('加载相机参数失败:', error)
    ElMessage.warning('加载相机参数失败，请检查网络连接')
  }
}

onMounted(() => {
  for(let i = 0; i < 20; i++){
    let port = "COM" + (i + 1)
    remotePortData.value.push(port)
  }
  if (authStore.currentUser) {
    console.log(authStore.currentUser)
    creatorId.value = authStore.currentUser.id
  }
     patientId.value =  props.selectedPatient.id
    //patientId.value = '202511150005'
  // 加载患者信息
  loadPatientInfo()
  // 启动检测
  startDetection()
  // 页面加载时自动连接WebSocket
  connectWebSocket()
  
  // 监听页面关闭或刷新事件
  window.addEventListener('beforeunload', handleBeforeUnload)
  
})

onUnmounted(() => {
  console.log('🔄 Detection组件正在卸载，开始清理资源...')
  
  try {
    // 清理定时器
    if (timerId.value) {
      clearInterval(timerId.value)
      timerId.value = null
      console.log('✅ 定时器已清理')
    } 
 
    // 断开WebSocket连接
    disconnectWebSocket()

    // 清理图表资源
    if (tiltCharts) {
      try {
        tiltCharts.dispose()
        console.log('✅ tiltCharts已清理')
      } catch (e) {
        console.warn('tiltCharts dispose error in onUnmounted:', e)
      }
      tiltCharts = null
    }
    
    if (rotationCharts) {
      try {
        rotationCharts.dispose()
        console.log('✅ rotationCharts已清理')
      } catch (e) {
        console.warn('rotationCharts dispose error in onUnmounted:', e)
      }
      rotationCharts = null
    }
    
    if (pitchCharts) {
      try {
        pitchCharts.dispose()
      } catch (e) {
      
      }
      pitchCharts = null
    }
    
    // 移除页面关闭事件监听器
    window.removeEventListener('beforeunload', handleBeforeUnload)
  } catch (error) {
  
  }
})

const startRecord = async () => { // 开始录屏
   try {
    console.log('🚀 正在开始录屏...')
    startTimer()
    // 验证患者信息
    if (!patientInfo.value || !patientInfo.value.sessionId) {
      throw new Error('缺少患者信息，无法开始录屏')
    }
    let screen_location = contenGridRef.value.getBoundingClientRect()
    let femtobolt_location = wholeBodyRef.value.getBoundingClientRect()




    let camera1_location = camera1Ref.value?.getBoundingClientRect()
    let camera2_location = camera2Ref.value?.getBoundingClientRect()
    let titile_height = 24
    // 调用后端API开始录屏
    const response = await fetch(`${BACKEND_URL}/api/detection/${patientInfo.value.sessionId}/start_record`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        patient_id: patientId.value,
        // 可以添加其他录屏参数
        creator_id: creatorId.value,        
        screen_location:[Math.round(screen_location.x), Math.round(screen_location.y) + titile_height, Math.round(screen_location.width), Math.round(screen_location.height)],
        camera1_location:[
          Math.round(camera1_location.x), Math.round(camera1_location.y)+ titile_height,
          Math.round(camera1_location.width), Math.round(camera1_location.height)
        ],
        camera2_location:[
          Math.round(camera2_location.x), Math.round(camera2_location.y)+ titile_height,
          Math.round(camera2_location.width), Math.round(camera2_location.height)
        ],
        femtobolt_location:[Math.round(femtobolt_location.x), Math.round(femtobolt_location.y) + titile_height, Math.round(femtobolt_location.width), Math.round(femtobolt_location.height)],
     
      })
    })
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }

    const result = await response.json()

    if (result.success) {
      // 保存会话ID和检测开始时间
      patientInfo.value.detectionStartTime = Date.now()
      console.log('✅ 录屏会话创建成功，会话ID:', patientInfo.value.sessionId)
      isRecording.value = true  
      // ElMessage.success('录屏已开始')
    } else {
      throw new Error(result.message || '开始录屏失败')
    }
  } catch (error) {
    ElMessage.error(`开始录屏失败: ${error.message}`)
    throw error
  }
}

const stopRecord = async () => {  // 停止录屏
  try {
    resetTimer()
    // 计算检测持续时间
    let duration = 0
    if (patientInfo.value.detectionStartTime) {
      duration = Math.floor((Date.now() - patientInfo.value.detectionStartTime) / 1000)
    }

   // 调用后端API停止检测
    const response = await fetch(`${BACKEND_URL}/api/detection/${patientInfo.value.sessionId}/stop_record`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        duration: duration
      })
    })
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
    }
    isRecording.value = false

  } catch (error) {
    console.error('❌ 停止检测失败:', error)
    ElMessage.error(`停止检测失败: ${error.message}`)
  }
}
function routerClick(){
  historyDialogVisible.value = true
}

const isRestart = ref(false) // 防止连击

// 单个刷新数据
function refreshClick(type) { 
  // 检查是否在冷却期内
  if (isRestart.value === true) {
    ElMessage.warning(`请勿连续点击设备重启按钮！请等待5秒后再试`)
    return
  }  
  // 设置冷却状态
  isRestart.value = true  
  // 5秒后重置状态
  setTimeout(() => {
    isRestart.value = false
  }, 5000)  
  ElMessage.warning(`🚀 发送重启设备请求...`)
  if (devicesSocket && devicesSocket.connected) {
    if(type == 'camera1'){
      devicesSocket.emit('restart_device', { device_type: 'camera1' })
    }else if(type == 'camera2'){
      devicesSocket.emit('restart_device', { device_type: 'camera2' })
    }else if(type == 'femtobolt'){
      devicesSocket.emit('restart_device', { device_type: 'femtobolt' })
    }else if(type == 'imu'){
      devicesSocket.emit('restart_device', { device_type: 'imu' })
    }else if(type == 'pressure'){
      devicesSocket.emit('restart_device', { device_type: 'pressure' })
    }else if(type == 'remote'){
      devicesSocket.emit('restart_device', { device_type: 'remote' })
    }
  } else {
    console.warn('⚠️ Socket服务未连接，无法重启设备！')
  }
}

async function closeDiagnosticMessage(e){
  isDiagnosticMessage.value = false
  if(e == '关闭'){
    isTip.value = false
  }
  if (e === true || (typeof e === 'object' && e)){
    try {
    // 清理定时器
    if (timerId.value) {
      clearInterval(timerId.value)
      timerId.value = null
      console.log('✅ 定时器已清理')
    }
    
    // 停止录制
    if (isRecording.value === true) {
      stopRecord()
      console.log('✅ 录制已停止')
    }

    const summary = typeof e === 'object' && e !== null ? {
      diagnosis_info: e.diagnosis_info ?? '',
      treatment_info: e.treatment_info ?? '',
      remark_info: (e.remark_info ?? e.suggestion_info ?? '')
    } : {
      diagnosis_info: diagnosticForm.value.diagnosis_info,
      treatment_info: diagnosticForm.value.treatment_info,
      remark_info: diagnosticForm.value.suggestion_info
    }
    await stopDetection(summary)
    // 断开WebSocket连接
    disconnectWebSocket()
    // 移除页面关闭事件监听器
    window.removeEventListener('beforeunload', handleBeforeUnload)
    emit('endChange',true)
    routeTo('/')
  } catch (error) {
    console.error('❌ Detection组件卸载时出错:', error)
    emit('endChange',true)
  }
   

  }

}
const isPhotoAlbum = ref(false)
function closePhotoAlbum(){
  isPhotoAlbum.value = false
}
function closecreatbox(e){
  if(e === true){
    loadPatientInfo()
  }
  isCloseCreat.value = false
}

function handleEditUserInfo(){
  isCloseCreat.value = true
}
function closePatientProfile(){
  historyDialogVisible.value =false
}
function closeViewUserInfo(){
  isViewUser.value = false
}
function viewClick(e){
  isExpand.value = e
}
</script>

<style scoped>
/* 全局容器 */
.detection-container-box {
  /* display: flex; */
  height: 100vh;
  background-color: #191d28;
  color: #FFFFFF;
}

.detection-container-box .el-row {
  margin: 0!important;
  height: calc(100%);
}

.username-line {
  width: 2px;
  height: 22px;
  margin: 0 10px;
  background-color: #fff;
}

.displaycontainer {
  width: 100%;
  height: 62px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 0 10px;
}

.displayleft {
  display: flex;
  align-items: center;
}
.icon-box{
  width: 32px;
  height: 32px;
  background-color: #374151;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: 10px;
  cursor: pointer;
}
.icon-box:hover{
  background-color: rgb(20 170 255 / 30%);
  border: 1px solid rgb(20 170 255 / 50%);
}
.startvideo-box{
  width: 130px;
  display: flex;
  align-items: center;
  margin-left: 10px;
  font-family:'Noto Sans SC Bold', 'Noto Sans SC Regular', 'Noto Sans SC';
  font-weight:700;
  font-style:normal;
  font-size:14px;
  color:#FFFFFF;
}
.conductanimated{
  margin-right: 5px;

  animation: fadeInOut 1s infinite;
}
@keyframes fadeInOut {
  0%, 100% { opacity: 0; } /* 初始状态和结束状态为完全透明 */
  50% { opacity: 1; } /* 中间状态为完全不透明 */
}

.body-posture-box{
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
}
.body-header-box{
  width: 100%;
  height: calc(50% - 7px) ;
  /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);

  border: 1px solid #262d40;
  border-radius: 4px;
}
.body-foot-box{
  margin-top: 15px;
  width: 100%;
  height: calc(50% - 7px) ;
  /* background:linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);

  border: 1px solid #262d40;
  border-radius: 4px;
}
.body-title-display{
  width: 100%;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 0 20px;
  font-family: "Noto Sans SC Bold", "Noto Sans SC Regular", "Noto Sans SC";
  font-weight: 700;
  font-style: normal;
  font-size: 20px;
  color: rgb(255, 255, 255);
}
.body-son-display{
  display: flex;
  align-items: center;
}
.connecttext{
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
}

.body-header-bottombox{
  width: 100%;
  height: calc(100% - 50px);
  display: flex;
  justify-content: center;
  box-sizing: border-box;
  padding: 0 20px;
}
.body-header-bottombox-left{
  width: 25%;
  height: calc(100%);
  display: flex;
  flex-direction: column;
  align-content:space-between;
}
.body-header-bottombox-lefttext{
  width: 100%;
  height: 33%;
  white-space:nowrap;
}
.body-header-bottombox-content{
  width: 40%;
  height: calc(100%);
  display: flex;
  flex-wrap: wrap;
  align-items:center;
}
.body-header-bottombox-right{
  width: 25%;
  height: calc(100%);
  display: flex;
  flex-direction: column;
  align-content:space-between;
}
.body-header-bottombox-righttext{
  width: 100%;
  height: 33%;
  white-space:nowrap;
  text-align: right;
}
.currencytext1{
  min-width: 100px;
  font-size: 16px;
  color: #FFFFFF;
  font-family: "Noto Sans SC";
  font-weight: 400;
  color: #D1D5DB;
}
.currencytext2{
  font-weight: 700;
  font-style: normal;
  font-size: 24px;
  color: #3BF2C6;
}
.currencytext3{
  width: 60px;
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color: #FFFFFF;
  display: inline-block;
  text-align: left;
}
.currencytext4{
  width: 20px;
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color:#D1D5DB;
  display: inline-block;
  text-align: left;
}
.body-footbottom-box{
  display: flex;
  align-items: center;
  justify-content: center;
  height: calc(100% - 50px);
}
.body-footbottom-left{
  width: 28%;
  height: calc(100%);
  display: flex;
  align-content: center;
  justify-content: center;
  flex-wrap: wrap;
}
.body-footbottom-leftbox{
  min-width: 215px;
  width: 80%;
  min-height: 60px;
  height: 20%;
  background: inherit;
  background-color: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0px 20px;
}
.body-footbottom-center{
  width: 40%;
  height: calc(100%);
}
.body-footbottom-topbox{
  display: flex;
  align-items: center;
  justify-content: space-around;
  width: 100%;
  height: 50px;
  font-weight: 400;
  font-style: normal;
  font-size: 24px;
  color: #FFFFFF;
}
.xline {
  position: absolute;
  width: calc(100% + 20px) ;
  border-top: 1px dashed red;
  top: 50%;
  left: -10px;
}

.yline {
  position: absolute;
  height:  calc(100% + 20px);
  border-left: 1px dashed red;
  top: -10px;
  left: 50%;
}
.body-footbottom-leftbottom{
  width: 100%;
  height: calc(100% - 60px);
  /* height: 281px; */
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  align-content:space-between ;
}

.body-userinfo-box{
  position: relative;
  z-index: 10;
  width: 100%;
  height: 346px;
  /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
}
.body-userinfo-expandbox{
  height: 638px ;
}
.body-userinfo-box1{
  width: 100%;
  height: 534px ;
  /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
}
.body-userinfo-box3{
  width: 100%;
  height: 100% ;
  /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
}


.body-video-box{
  width: 100%;
  height:  calc(100% - 348px - 14px) ;
  /* background: linear-gradient(135deg, rgba(42, 54, 73, 1) 0%, rgba(42, 54, 73, 1) 0%, rgba(34, 43, 56, 1) 100%, rgba(34, 43, 56, 1) 100%); */
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
  margin-top: 15px;
}
.body-video-box1{
  width: 100%;
  height:  calc(100% - 534px - 14px) ;
  background: linear-gradient(135deg, #1a1e2a 0%,  #222b38 100%);
  border: 1px solid #262d40;
  border-radius: 4px;
  margin-top: 15px;
}
.body-userinfo-content{
  width: 100%;
  height: calc(100% - 50px);
  padding: 15px;
}
.body-userinfo-content-top{
  position: relative;
  width: calc(100%);
  height: 116px;
  background-color: #374151;
  border-radius: 8px 8px 0 0;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  padding: 0 20px;
}
.body-userinfo-content-bottom{
  padding:10px;
  padding-top: 20px;
  position: relative;
  width: calc(100%);
  height: calc(100% - 116px);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-content: start;
  border-width: 0px 1px 1px;
  border-right-style: solid;
  border-bottom-style: solid;
  border-left-style: solid;
  border-right-color: rgb(55, 65, 81);
  border-bottom-color: rgb(55, 65, 81);
  border-left-color: rgb(55, 65, 81);
  border-top-style: initial;
  border-top-color: initial;
  border-radius: 0px 0px 8px 8px;
  box-shadow: none;
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
}


.body-userinfo-content-bottom0{
  padding:10px;
  padding-top: 20px;
  position: relative;
  width: calc(100%);
  height: calc(100% - 116px);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-content: start;
  border-width: 0px 1px 1px;
  border-right-style: solid;
  border-bottom-style: solid;
  border-left-style: solid;
  border-right-color: rgb(55, 65, 81);
  border-bottom-color: rgb(55, 65, 81);
  border-left-color: rgb(55, 65, 81);
  border-top-style: initial;
  border-top-color: initial;
  border-radius: 0px 0px 8px 8px;
  box-shadow: none;
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
}
.body-userinfo-content-bottom1{
  padding:10px;
  padding-top: 10px;
  position: relative;
  width: calc(100%);
  height: calc(100% - 116px);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-content: start;
  border-width: 0px 1px 1px;
  border-right-style: solid;
  border-bottom-style: solid;
  border-left-style: solid;
  border-right-color: rgb(55, 65, 81);
  border-bottom-color: rgb(55, 65, 81);
  border-left-color: rgb(55, 65, 81);
  border-top-style: initial;
  border-top-color: initial;
  border-radius: 0px 0px 8px 8px;
  box-shadow: none;
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
}

.body-userinfo-content-bottom2{
  padding:10px;
  padding-top: 20px;
  position: relative;
  width: calc(100%);
  height: calc(100% - 116px);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-content: start;
  border-width: 0px 1px 1px;
  border-right-style: solid;
  border-bottom-style: solid;
  border-left-style: solid;
  border-right-color: rgb(55, 65, 81);
  border-bottom-color: rgb(55, 65, 81);
  border-left-color: rgb(55, 65, 81);
  border-top-style: initial;
  border-top-color: initial;
  border-radius: 0px 0px 8px 8px;
  box-shadow: none;
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
}
.userinfo-disyplay1{ 
  display: flex;
  width: calc(64%);
  padding-top: 20px;
}
.userinfo-disyplay2{ 
  display: flex;
  width: calc(36%);
  padding-top: 20px;
}
.userinfo-disyplaypadding1{
  width: calc(64%);
  padding-bottom: 15px;
}
.padding10{
  padding-bottom: 5px;
}
.userinfo-disyplaypadding2{
  width: calc(36%);
  padding-bottom: 15px;
}
.userinfo-disyplaypadding3{
  width: calc(100%);
  padding-bottom: 15px;
}

.userinfo-disyplaypadding4{
  /* display: flex; */
  width: calc(64%);
  padding-bottom: 5px;
}
.userinfo-disyplaypadding5{
  /* display: flex; */
  width: calc(36%);
  padding-bottom: 5px;
}
.userinfo-disyplaypadding6{
  /* display: flex; */
  width: calc(100%);
  padding-bottom: 5px;
}

.useravatar-box{
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background: #303947;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 35px;
}
.userinfo-text-top{
  display: flex;
  align-items: center;
}
.userinfo-text1{
  font-weight: 700;
  font-style: normal;
  color: #FFFFFF;
  font-size: 20px;
}
.userinfo-text2{
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color: rgba(255, 255, 255, 0.6);
}
.userinfo-text3{
  font-family: "Noto Sans SC Bold", "Noto Sans SC Regular", "Noto Sans SC";
  font-weight: 700;
  font-style: normal;
  font-size: 16px;
  color: rgb(255, 255, 255);
  margin-top: 15px;
}
.userinfo-text4{
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.6);
  width: 60px;
}

.userinfo-text5{
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color: rgb(255, 255, 255);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.userinfo-line{
  width: 2px;
  height: 16px;
  background: rgba(255, 255, 255, 0.6);
  margin: 0 8px;
}
.userinfo-edit-img{
  position: absolute;
  right: 15px;
  top: 15px;
}
.body-video-content{
  width: 100%;
  height: calc(100% - 50px);
  padding: 15px;
  box-sizing: border-box;
  display: flex;
  align-content: space-between;
  flex-wrap: wrap;
  justify-content: center;
}
.body-video-imgbox1{
  position: relative;
  width: 100%;
  height: calc(50% - 7px);
}

.body-video-imgbox2{
  position: relative;
  width: 100%;
  height: calc(50% - 8px);
}
.body-video-imgbox3{
  position: relative;
  width: 100%;
  height: calc(100%);
}
.patientInfotop1{
  font-weight: 700;
  font-style: normal;
  font-size: 20px;
  color: #FFFFFF;
  margin:0 30px;
  margin-left:40px
}
.patientInfotop2{
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color: #FFFFFF;
}
.endbutton{
  width: 72px;
  height: 28px;
  background-color: rgba(11, 148, 213, 1);
  border:1px solid rgba(11, 148, 213, 1);
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: #D7D7D7;
  margin-left:20px
}
.endbutton:hover {
  background-color: #14aaff;
  border:1px solid #14aaff;
  color: #fff;
}
.pop-up-mask{
  position: fixed;
  z-index: 99;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.7);
}

.pop-up-tip-container {
  width: 400px;
  height:220px;
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  margin: auto;
  border-radius: 10px;
  background: #1b202c;
  /* background: linear-gradient(135deg, rgba(53, 67, 90, 1) 0%, rgba(53, 67, 90, 1) 0%, rgba(62, 79, 105, 1) 99%, rgba(62, 79, 105, 1) 100%); */
}
.pop-up-camera-container{
  width: 668px;
  height:630px;
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  margin: auto;
  background: linear-gradient(135deg, rgb(53, 67, 90) 0%, rgb(53, 67, 90) 0%, rgb(62, 79, 105) 99%, rgb(62, 79, 105) 100%);
  border-radius: 10px;
  box-shadow: rgb(17, 24, 33) 0px 0px 10px;
}
.pop-up-camera-header{
  width: 100%;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 0 40px;
  font-family: 'Noto Sans SC';
  font-weight: 700;
  font-style: normal;
  font-size: 20px;
  color: #FFFFFF;
  text-align: left;
  border-radius:10px 10px 0 0;
}

.pop-up-tip-header{
  width: 100%;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  padding: 0 30px;
  font-family: 'Noto Sans SC';
  font-weight: 700;
  font-style: normal;
  font-size: 20px;
  color: #FFFFFF;
  text-align: left;
}
.tipconfirmbutton-box{
  width:100%;
  display:flex;
  align-items: center;
  justify-content: center;
}
.tipconfirmbutton{
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: rgb(255, 255, 255);
  background:#0b94d5;
  border:1px solid #0b94d5;
  width: 80px;
  height: 40px;
}
.tipconfirmbutton:hover{
  background:#14aaff;
  border:1px solid #14aaff;
}
.pop-up-tip-text{
  width:100%;
  font-weight: 400;
  font-style: normal;
  font-size: 16px;
  color: #FFFFFF;
  text-align: center;
  padding:30px 10px;
}
.pop-up-camera-body{
  padding: 20px 40px;
}
.pop-up-camera-display{
  display: flex;
  align-items: center;
}
.pop-up-camera-line{
  width: 4px;
  height: 13px;
  background-color: rgba(38, 111, 255, 1);
  margin-right: 3px;
}
.pop-up-camera-title{
  font-weight: 700;
  font-style: normal;
  font-size: 15px;
  color: #FFFFFF;
}
.pop-up-camera-body :deep(.el-input__wrapper)  {
  background-color: #2a3649;
  border-width: 1px;
  border-style: solid;
  border-color: #2a3649;
  border-radius: 4px;
  box-shadow: none;
  height: 40px;

}
.pop-up-camera-body :deep(.el-input__wrapper:hover)  {
  border-color: rgba(38, 111, 255, 1);


}
.pop-up-camera-body :deep( .el-input__inner)  {
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  letter-spacing: normal;
  color: #FFFFFF;

}
.pop-up-camera-name{
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: rgba(255,255,255,0.6);
  width: 60px;
  text-align: right;
  margin-right: 20px;
}
.pop-up-camera-radio{
  width: 70px;
  height: 40px;
  background: inherit;
  background-color: rgba(40, 40, 40, 1);
  box-sizing: border-box;
  border-width: 1px;
  border-style: solid;
  border-color: rgba(54, 54, 54, 1);
  border-radius: 4px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.pop-up-camera-display :deep(.el-radio__label){
  font-weight: 400;
  font-style: normal;
  color: #FFFFFF;
  font-size: 14px;
}
.pop-up-camera-display :deep(.el-radio){
  width: 70px;
  height: 40px;
  background: inherit;
  background: #2a3649;
  box-sizing: border-box;
  border-width: 1px;
  border-style: solid;
  border-color: #4a576b;
  border-radius: 4px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0;
}
.pop-up-camera-display :deep(.el-radio.is-checked){
  width: 70px;
  height: 40px;
  background: inherit;
  background-color: #2a3649;
  box-sizing: border-box;
  border-width: 1px;
  border-style: solid;
  border-color: #14aaff;

}
.pop-up-camera-display :deep(.is-checked .el-radio__label){
  color: #14aaff;
}

.pop-up-camera-display :deep(.el-radio__input.is-checked .el-radio__inner){
  background: #14aaff;
  border-color: #14aaff;
}
.pop-up-camera-display :deep(.el-radio__input.is-checked .el-radio__inner){
  background: #14aaff;
  border-color: #14aaff;
}

.pop-up-camera-display :deep(.el-radio__input.is-checked .el-radio__inner:after){
  background-color: #2a3649;
}
.pop-up-camera-display :deep(.el-radio__inner){
  background-color: #2a3649;
  border-color: #4a576b;
}

</style>
<style> 
.historyDialogVisible.el-dialog{
  --el-dialog-margin-top: 0 !important;
  margin-bottom: 0;
}
.historyDialogVisible .el-dialog__body{
  padding: 0;
}
.pop-up-camera-container .form-actions-display{
  display: flex;
  justify-content: flex-end;
  padding-top: 40px;
  padding-right: 10px;
}
.calibration-zero{
  width: 72px;
  height: 28px;
  background-color: rgb(69, 91, 123);
  display:flex;
  align-items:center;
  justify-content:center;
  border-radius: 4px;
  box-shadow: none;
  font-family: "Noto Sans SC";
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: rgb(255, 255, 255);
  margin-left:10px;
  cursor:pointer;
}
.calibration-zero:hover{
  background-color: #14AAFF;
}
.noImageSvg-bg{
  display:flex;
  justify-content:center;
  align-items:center;
}

.pop-up-camera-container .formreturnCancel{
  width: 80px;
  height: 40px;
  background: rgba(89, 113, 148, 1);
  border: 1px solid rgba(89, 113, 148, 1);
  font-family: 'Noto Sans SC';
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.6);
}
.pop-up-camera-container .formreturnCancel:hover{
  background: #14aaff;
  color:#ffffff;
}
.pop-up-camera-container .formsaveCancel {
  width: 80px;
  height: 40px;
  background: #0b94d5;
  font-family: 'Noto Sans SC';
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  color: #FFFFFF;
}
.pop-up-camera-container .formsaveCancel:hover{
  background: #14AAFF;
  color:#ffffff;
}
.big-img{
  position: absolute;
  left: 10px;
  top: 10px;
  width: 30px;
  height: 30px;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}


</style>
<style>
.pop-up-camera-display .el-select__placeholder {
  color: #ffffff;
  font-size: 14px;
}
.pop-up-camera-display  .el-select__wrapper {
  background-color: #2a3649;
  border-width: 1px;
  border-style: solid;
  border-color: transparent;
  border-radius: 4px;
  box-shadow: none;
  height: 40px;
}
.pop-up-camera-display  .el-select__wrapper:hover{
  border-color: #3d4c65;
  box-shadow: 0 0 0 1px transparent inset;
}
</style>