chenyc
2024-01-15 191100aca6b5afac1d3c76afeea56b3063b81071
src/views/home/index.vue
@@ -1,6 +1,8 @@
<template>
  <div class="homeclass">
    <!-- {{dialogVisible}} -->
    <div class="page" v-if="!dialogVisible">
        <el-row style="height: 11.3%;">
        </el-row>
        <el-row style="height: 50%;margin-bottom: 2%;" :gutter="20">
@@ -143,25 +145,26 @@
                  机位/床位号
                </div>
              </div>
              <div style="height: 75%;">
              <div style="height: 81%;background-color: #FFFFFF;">
                <div class="textjuzhong" style="background: rgba(243, 247, 243, 0.3); font-size: 6rem; font-weight: 800; color: #DFB144;">
                  {{ patientInfo.deviceNo }}
                </div>
              </div>
          </el-col>
          <el-col :span="17">
            <div style="height: 25%;">
            <!-- <div style="height: 25%;">
                <div class="textjuzhong" style="background: #DFB144; font-size: 2rem; color: #FFFFFF;">
                  治疗信息
                </div>
              </div>
              <div style="height: 75%;">
                <div style="background: rgba(243, 247, 243, 0.3); height: 100%; width: 100%; font-size: 2.5rem; line-height: 4.5rem; font-weight: 800; color: #FFFFFF; text-align: center;padding-top: 1rem;">
                  <span style="font-size: 4rem; color:#DFB144 ; " >干体重  {{patientInfo.pureWeight}}  kg</span>
              </div> -->
              <div style="height: 100%;background-color: #FFFFFF;">
                <div ref="myChartRef" style="background: rgba(243, 247, 243, 0.3); height: 100%; width: 100%; font-size: 2.5rem; line-height: 4.5rem; font-weight: 800; color: #FFFFFF; text-align: center;padding-top: 1rem;">
                  <!-- <div    ref="myChartRef" style="height: 300px; width: 100%;"></div> -->
                  <!-- <span style="font-size: 4rem; color:#DFB144 ; " >干体重  {{patientInfo.pureWeight}}kg</span>
                  <br>
                  <span > 透析器:{{patientInfo.txq}}</span>
                  <span > 治疗模式:{{patientInfo.medMethod}}</span>
                  <span > 灌流器:{{patientInfo.glq}}</span>
                  <span > 灌流器:{{patientInfo.glq}}</span> -->
                </div>
              </div>
          </el-col>
@@ -177,7 +180,7 @@
              <el-row>
                <el-col   :span="24" style="text-align: right; line-height: 67px;padding-right: 0px; font-size: 40px;font-weight: 400;color: #EB6F1C;">
                  <div v-if="!dialogVisible">{{clockNum}}S</div>
                  <el-input v-else  v-model="inputCode" ref="inputRef" id="inputCode"  style="width: 200px; height: 40px;"  @change="inputChabge"
                  <el-input   v-else  v-model="inputCode" ref="inputRef" id="inputCode"  style="width: 200px; height: 40px;ime-mode:active"  @change="inputChabge"
                    placeholder="请输入患者卡号或扫描条码" />
                </el-col>
              </el-row>
@@ -185,7 +188,10 @@
          </el-row>
        </div>
        <div class="rWrapp">
          <video id="myVideo" preload="preload" autoplay loop muted />
          <video ref="video" id="myVideo"  preload="preload" autoplay loop muted   />
          <canvas ref="canvas" width="{this.width}" height="{this.height}" />
          <div style="text-align: center; font-size: 2rem; color: bisque;margin-top: 1rem;">请将脸部对准摄像头</div>
        </div>
        <div v-if="imgSrc" class="img_bg_camera" style="margin-top: 200px;">
@@ -193,7 +199,7 @@
          <img :src="imgSrc"  class="tx_img" />
        </div>
        <div style="margin-top: 0px; z-index: -1;position:absolute;" >
          <canvas ref="myCanvas" id="myCanvas" class="myCanvas" width="200" height="200" ></canvas>
        </div>
        <div class="footer" style="text-align: right;">
          <div class="fanhuikey" v-if="!dialogVisible" @click="fuxuan">
@@ -201,72 +207,56 @@
          </div>
        </div>
    </div>
    <el-dialog title="提示" v-model="netLink" width="30%">
    <!-- <el-dialog title="提示" v-model="netLink" width="30%">
      <span>无法链接到网络!</span>
    </el-dialog>
    </el-dialog> -->
  </div>
</template>
<script setup lang="ts">
import * as echarts from 'echarts';
import { detectSingleFace, nets, matchDimensions, resizeResults, draw, SsdMobilenetv1Options, Box } from 'face-api.js'
import * as faceapi from 'face-api.js'
import { userInfoStore } from '@/stores/userInfo'
import { sockteStore } from '@/stores/sockteInfo'
import { ipcRenderer } from 'electron'
import { patientInfoStore } from '@/stores/patient'
import { updatePatient } from '@/api/user/index'
import { updatePatient,listWeightHistory,listBPHistory } from '@/api/user/index'
import os from "os"
import Speech from 'speak-tts'
import { reactive,computed, toRefs, onMounted, watch, ref } from "vue"
import { reactive,computed, toRefs, onMounted, watch, ref, getCurrentInstance } from "vue"
import { sendPationCodeApi } from '../../samples/httpApi'
import { formatDate } from '@/utils/formatTime'
import { formatDate,jgTime,isworkTime } from '@/utils/formatTime'
import { confingInfoStore } from '@/stores/StoresConfing'
import {base64toFile} from '@/samples/faceApi'
import{initPort} from '@/samples/portApi'
import{initPort as oumulongHbp9030 } from '@/samples/deviceApi/oumulong-HBP-9030'
import { ElLoading, ElMessage } from 'element-plus'
let trackerTask: any = null;
// 标识用的画布
const myCanvas = ref<HTMLCanvasElement | null>(null);
import{initPort as  TM2655VP} from '@/samples/deviceApi/TM2655VP'
import{initPort as zhiRongT605 } from '@/samples/deviceApi/zhiRongT605'
import{initPort as zhiRongHehui } from '@/samples/deviceApi/zhiRongHehui'
import{initPort as taiHengM523 } from '@/samples/deviceApi/taiHengM523'
import{initPort as XK3190A12 } from '@/samples/deviceApi/XK3190A12'
import {initPort as mbp7000} from '@/samples/deviceApi/mbp7000'
import {initPort as M503} from '@/samples/deviceApi/M503'
import {initPort as seca102} from '@/samples/deviceApi/seca102'
// 读取体重文件
import{todatatzs } from '@/samples/deviceApi/seca101'
import {ElMessage } from 'element-plus'
const { proxy } = getCurrentInstance() as any;
// 人脸检测对象
const options = new SsdMobilenetv1Options({
  // 最小置信阈值
  // 默认值:0.5
  minConfidence: 0.5
})
const canvas = ref('canvas') // 图像画布
const video = ref('video') // 视频元素
const stream = ref(null) // 当前流
const getUserMediaFail = ref(false) // 获取用户媒体失败
let lsDateTime:any=new Date()
let imgSrc:'';
const msg = ref<string>("没识别到人脸...");
// 实例人脸检查器
const myTracker: any = new tracking.ObjectTracker("face");
myTracker.setInitialScale(4);
myTracker.setStepSize(2);
myTracker.setEdgesDensity(0.1);
// 监听人脸检查器
myTracker.on("track", (event: tracking.TrackEvent) => {
  const context = myCanvas.value?.getContext("2d") as CanvasRenderingContext2D;
  if (myCanvas.value) {
    context.clearRect(0, 0, myCanvas.value.width, myCanvas.value.height);
  }
  if (event.data.length === 0) {
    msg.value = "没识别到人脸...";
  } else if(event.data.length === 1) {
    trackerTask.stop();
    msg.value = "检测到人脸";
    const myCanvas = document.getElementById("myCanvas");//
    const thisContext = myCanvas?.getContext("2d");
    const myVideo = document.querySelector("#myVideo") as HTMLVideoElement;
    thisContext.drawImage(myVideo, 0,0, 250, 200);
    imgSrc = myCanvas?.toDataURL('image/png');
    // 转文件
    // 识别框显示才能到传阿里云识别
    if(dialogVisible.value){
      base64toFile(imgSrc)
    }
    setTimeout(() => {
      console.log(configData.value.face_push+'秒跑一次人脸识别')
      trackerTask.run();
    }, configData.value.face_push*1000);
    // @ts-ignore
    if (typeof window.stream === "object") {
      myVideo.srcObject = null;
      // @ts-ignore
      window.stream.getTracks().forEach((track) => track.stop());
    }
  }
});
let timer: any = 0
let timer:any=new Date()
const date=ref('')
const timeShidaun=ref('')
// 语音播报
@@ -313,8 +303,16 @@
    ipcRenderer.invoke('logger', '网络已经断开')
  }else{
    ipcRenderer.invoke('logger', '网络已经恢复')
  }
  return !sockte.netLink
})
watch(netLink,()=>{
  if(!netLink.value){
    ElMessage.success('网络已经连接')
  }else{
    ElMessage.warning('网络已断开,等待重连')
  }
})
// 体重
@@ -346,59 +344,6 @@
})
const settime = () => {
  clockNum.value = patientInfoStore().viewNumber
  // // 清除定时器
  // clearInterval(timerNum.value)
  // if(timerNum.value===0){
  //   timer = setInterval(() => {
  //       if (clockNum.value > 0) {
  //         clockNum.value--
  //       }
  //       else {
  //         // clearInterval(timer)
  //         clockNum.value = patientInfoStore().viewNumber
  //         patientInfoStore().setpatientInfo({
  //           id: 0,
  //           code: '',
  //           name: '',
  //           patientAvatarIcon: '',
  //           deviceCode: '',
  //           hemoCode: '',
  //           pureWeight: '',
  //           datetime: ''
  //         })
  //         sockteStore().setweightSockte({
  //           type: '体重秤',
  //           deviceName: '',
  //           result: '0',
  //           resultTime: '',
  //           state: 2
  //         })
  //         sockteStore().setxyjSockte({
  //           type: '血压计',
  //           deviceName: '',
  //           result: '',
  //           resultTime: '',
  //           state: 2
  //         })
  //         sockteStore().setfaceSockte({
  //           type: '人脸识别',
  //           deviceName: '',
  //           result: '',
  //           resultTime: '',
  //           state: 2
  //         })
  //         aimTSL.value = ''
  //         gao_ya.value = ''
  //         di_ya.value = ''
  //         mai_bu.value = ''
  //       }
  //     }, 1000)
  //   // 记录定时器
  //   timerNum.value = timer
  // }else{
  // }
}
//发送消除某些状态
const fuxuan=()=>{
@@ -450,9 +395,147 @@
    dialogVisible.value = true
  }else{
    console.log('关闭人脸识别')
    dialogVisible.value = false
    dialogVisible.value = true
  }
}
const huatu=(series: { name: string; type: string; stack: string; data: any; }[],xAxis: any[],legendData:any[],textTitle:string)=>{
  const myChart = echarts.init(proxy.$refs.myChartRef);
      const option = {
        title: {
          text: textTitle,//'体重趋势图',
          borderRadius:5,
          backgroundColor:"#409EFF",
          left:20,
          textStyle:{
            color:'#ffffff',
            fontSize:18
          }
        },
        tooltip: {
          trigger: 'axis',
        },
        legend: {
          data:legendData //['透前体重', '透后体重', '干体重']
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        toolbox: {
          show: true,
          feature: {
            // restore: {}
          }
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: xAxis
        },
        yAxis: {
          type: 'value',
          axisLabel: {
            formatter: '{value} kg'
          },
          min:30,
          minInterval:1,
        },
        series:  series
      };
      myChart.setOption(option);
}
// 体重趋势图
const intiTubiao=()=>{
  console.log('----------3333')
  const xAxisData: any[]=[]
  const series=[
    {
      name: '透前体重',
      type: 'line',
      color:'#E6A23C',
      smooth: true,
      data: []
    },
    {
      name: '透后体重',
      color:'#409EFF',
      type: 'line',
      smooth: true,
      data: <any>[]
    },
    {
      name: '干体重',
      type: 'line',
      color:'red',
      smooth: true,
      data: []
    },
  ]
  console.log(patientInfo.value)
  listWeightHistory(`patientCode=${patientInfo.value.code}`).then(res=>{
    console.log(res.data,'-----------------------')
    if(res.data.length>0){
      res.data.forEach((e:any)=>{
        xAxisData.push(e.透析日期.substring(5,10))
        series[0].data.push(e.透前称重)
        series[1].data.push(e.透后称重)
        series[2].data.push(e.干体重)
      })
      const legendData=['透前体重', '透后体重', '干体重']
      huatu(series,xAxisData,legendData,'体重趋势图')
    }
  })
}
// 血压趋势图
const intiTubiaoXY=()=>{
  const xAxisData: any[]=[]
  const series=[
    {
      name: '透前伸缩压',
      type: 'line',
      color:'#E6A23C',
      smooth: true,
      data: []
    },
    {
      name: '透前舒张压',
      color:'#409EFF',
      type: 'line',
      smooth: true,
      data: <any>[]
    },
    {
      name: '透后伸缩压',
      type: 'line',
      color:'#606266',
      smooth: true,
      data: []
    },{
      name: '透后舒张压',
      type: 'line',
      color:'#E6A23C',
      smooth: true,
      data: []
    }
  ]
  listBPHistory(`patientCode=${patientInfo.value.code}`).then(res=>{
    console.log(res.data,'--------sss---')
    if(res.data.length>0){
      res.data.forEach((e:any)=>{
        xAxisData.push(e.透析日期.substring(5,10))
        series[0].data.push(e.透前伸缩压)
        series[1].data.push(e.透前舒张压)
        series[2].data.push(e.透后伸缩压)
        series[3].data.push(e.透后舒张压)
      })
      const legendData=['透前伸缩压', '透前舒张压', '透后伸缩压','透后舒张压']
      huatu(series,xAxisData,legendData,'血压趋势图')
    }
  })
}
// 监控患者信息变化
watch(
@@ -462,8 +545,9 @@
    patientCodeLsXy = ''
    aimTSL.value = ''
      // 定时数秒器
    settime()
    if (patientInfo.value.id !== 0 && patientInfo.value.name !== '' && patientInfo.value.isScheduled === 1) {
      settime()
      // 人脸识别成功后 1查看是否开启测温
      // console.log(`患者信息识别成功:${patientInfo.value.name}`)
      ipcRenderer.invoke('logger', `患者信息识别成功:${patientInfo.value.name}`)
@@ -471,6 +555,13 @@
      dialogVisible.value = false
      speech.value?.speak({ text: str }).then(() => {
      })
      if(configData.value.deviceType==='体重秤'){
        setTimeout(()=>{intiTubiao()},1000)
      }else{
        setTimeout(()=>{intiTubiaoXY()},1000)
      }
      sockteStore().setweightSockte({
        type: "体重秤",
        state: 2,
@@ -485,12 +576,15 @@
        result: "",
        resultTime: ""
      })
    }
    // 没有找到患者
    else if (patientInfo.value.name === '') {
      ipcRenderer.invoke('logger', '接收到的患者为空')
      // console.log('接收到的患者为空')
      console.log('接收到的患者为空')
      if (isUseFaceRecogService.value) {
        dialogVisible.value = true
      }
@@ -498,6 +592,8 @@
    }
    // 没有排班
    else if (patientInfo.value.isScheduled === 0) {
      setTimeout(()=>{intiTubiao()},1000)
      settime()
      ipcRenderer.invoke('logger', `患者没有排班:${patientInfo.value.name}`)
      // console.log( `患者没有排班:${patientInfo.value.name}`)
      //关闭人脸弹框
@@ -527,6 +623,8 @@
watch(
  () => weightInfo.value.resultTime,
  async () => {
    const X= jgTime(timer,new Date())
    console.log(X,'收到体重',configData.value.BobaoJg)
    // 体重不能0
    if (weightInfo.value.result !== "0"&&patientInfo.value.code!=='') {
        ipcRenderer.invoke('logger', `体重变化了:${weightInfo.value.result}`)
@@ -537,16 +635,15 @@
          weight: weightInfo.value.result,
          bloodPressure: ''
        }
        settime()
        if (patientCodeLs !== mode.patientCode) {
          settime()
          // 定时数秒器
          const tt = mode.weight.replace('.', '点')
          speech.value?.speak({ text: `称重完成,${tt}kg` }).then(() => {
          speech.value?.speak({ text: `称重完成,${tt}千克` }).then(() => {
            console.log("播报完成...")
          })
          patientCodeLs = mode.patientCode
          fasongNum.value=0
          // console.log(`开始发送结果到服务器:患者:${patientInfo.value.name},体重结果:${weightInfo.value.result}`)
          ipcRenderer.invoke('logger', `开始发送结果到服务器:患者:${patientInfo.value.name},体重结果:${weightInfo.value.result}`)
          console.log(`开始发送结果到服务器:患者:${patientInfo.value.name},体重结果:${weightInfo.value.result}`)
          sundModeTz()
@@ -561,7 +658,12 @@
        }else if(Number(patientInfo.value.pureWeight) !== 0&&patientInfo.value.isAfterMed===1 && patientInfo.value.preWeight>10){
          aimTSL.value = (Number(patientInfo.value.preWeight)- Number(patientInfo.value.pureWeight) - Number(patientInfo.value.clothesWeight)).toFixed(2)
        }
      }
    }// 要过4秒才能重复播报这个消息
    else if(patientInfo.value.code===''&&weightInfo.value.result !== "0"&&X>configData.value.BobaoJg){
      timer=new Date()
      speech.value?.speak({ text: "没有识别的患者,请先验证患者" }).then(() => {
      })
    }
  }
);
// 血压发送了变化
@@ -573,9 +675,9 @@
      console.log(`血压发生变化了:${weightInfo.value.result}`)
      const list = xyjInfo.value.result.split(',')
      if (list.length === 3) {
        gao_ya.value = list[0]
        di_ya.value = list[1]
        mai_bu.value = list[2]
        gao_ya.value = Number(list[0]).toString()
        di_ya.value = Number(list[1]).toString()
        mai_bu.value = Number(list[2]).toString()
      }
      // 患者信息为空
      if (patientInfo.value.id === 0) {
@@ -697,10 +799,23 @@
);
// 文本框点击事件
const inputChabge = () => {
  sendPationCodeApi(inputCode.value)
  setTimeout(function () {
    inputCode.value = ''
  }, 1000)
  console.log(inputCode.value.substring(0,4)==='1553')
  // 更具沅江肾病医院的二维码匹配
  if(inputCode.value.substring(0,4)==='1553'){
    const list=inputCode.value.split(':')
    console.log(list)
    sendPationCodeApi(list[1])
    setTimeout(function () {
      inputCode.value = ''
    }, 5000)
  }else{
    sendPationCodeApi(inputCode.value)
    setTimeout(function () {
      inputCode.value = ''
    }, 5000)
  }
}
// 点击10下关闭程序
const guyanbi = () => {
@@ -709,10 +824,8 @@
    ipcRenderer.send('winClose')
  }
}
const openPort=()=>{
  initPort('com5',115200)
}
onMounted(() => {
  console.log(0%5)
  console.log('页面初始化', os.hostname())
  setTimeout(()=>{
    console.log('8秒后执行')
@@ -724,14 +837,69 @@
    }
    // 是否开启血压计联机
    if(configData.value.Is_xyj){
      oumulongHbp9030(configData.value.xueyanjiPortPath,configData.value.xueyanjiBaudRate)
      if(configData.value.xyj_type==='TM2655'){
        TM2655VP(configData.value.xueyanjiPortPath,configData.value.xueyanjiBaudRate)
      }else if(configData.value.xyj_type==='mbp7000'){
        mbp7000(configData.value.xueyanjiPortPath,configData.value.xueyanjiBaudRate)
      }
      else{
        oumulongHbp9030(configData.value.xueyanjiPortPath,configData.value.xueyanjiBaudRate)
      }
    }
      // 是否开启脸识别
    // 是否开启志荣体重秤联机
    if(configData.value.Is_tzc){
      //台衡M523
      if(configData.value.tzc_type==='taiHengM523'){
        taiHengM523(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }
      else if(configData.value.tzc_type==='M503'){
        M503(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }else if(configData.value.tzc_type==='seca102'){
        seca102(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }
      // seca101读取文件
      else if(configData.value.tzc_type==='seca101'){
        console.log('体重是读取文件')
      }// 耀华XK3190-A12
      else if(configData.value.tzc_type==='XK3190-A12'){
        XK3190A12(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }else if(configData.value.tzc_type==='zhiRongHehui'){
        zhiRongHehui(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }
      else{
        zhiRongT605(configData.value.tzcPortPath,configData.value.tzcBaudRate)
      }
    }
    // 是否开启脸识别
    isUseFaceRecogService.value = configData.value.isUseFaceRecogService
    console.log('人脸识别',isUseFaceRecogService.value)
    if (isUseFaceRecogService.value) {
      console.log('开启人脸识别')
      trackerTask = tracking.track("#myVideo", myTracker, { camera: true });
      faceapi.env.monkeyPatch({
          Canvas: HTMLCanvasElement,
          Image: HTMLImageElement,
          ImageData: ImageData,
          Video: HTMLVideoElement,
          createCanvasElement: () => document.createElement('canvas'),
          createImageElement: () => document.createElement('img')
      })
      // 获取用户媒体流
      getUserMedia(
        (streams: null) => {
          //后续用于停止视频流
          stream.value = streams
          //显示视频
          if (video.value) {
            video.value['srcObject'] = streams
          }
        },
        (error: any) => (getUserMediaFail.value = true)
      )
      init()
      setTimeout(()=>{
        detectFace()
      },2000)
      dialogVisible.value = true
    }else{
      console.log('关闭人脸识别')
@@ -743,7 +911,6 @@
      if(clockNum.value===0){
        fuxuan()
      }
      inputRef.value.focus();
      date.value=formatDate(new Date(),'YYYY-mm-dd HH:MM')
      if(Number(date.value.substring(11,13))<12){
        timeShidaun.value='上午好!'
@@ -752,6 +919,16 @@
      }else {
        timeShidaun.value='晚上好!'
      }
      // 验证人脸识别已经通过但是还没有体重数据主动获取数据
      if(patientInfo.value.name!==''&&weightInfo.value.result==='0'&&configData.value.Is_tzc&&configData.value.tzc_type==='seca101'){
        console.log('主动获取体重')
        todatatzs(patientInfo.value.datetime)
      }
      if(inputRef.value!==null){
         inputRef.value.focus();
      }
    }, 1000)
    speech.value = new Speech();
    speech.value?.setLanguage('zh-CN')
@@ -760,8 +937,110 @@
    })
  },8000)
})
/** @name 人脸检测 */
const detectFace:any = async () => {
  //非常重要:防止卡死
  await new Promise((resolve) => requestAnimationFrame(resolve))
  //绘制取景框
  // drawViewFinder()
  if (!canvas.value || !video.value || !video.value.currentTime || video.value.paused || video.value.ended)
    return detectFace()
  // 检测图像中具有最高置信度得分的脸部
  const result = await detectSingleFace(video.value, options)
  if (!result) return detectFace()
  // 匹配尺寸
  const dims = matchDimensions(canvas.value, video.value, true)
  // 调整检测到的框的大小,以防显示的图像的大小与原始
  const resizedResult = resizeResults(result, dims)
  const box = resizedResult.box
  // 不要小头像
  if(box._height<120) return detectFace()
  //检测框是否在取景框内
  // if (!checkInViewFinder(box)) return detectFace()
  // drawViewFinder()
  //将检测结果绘制到画布(此处不用,可以直接用来绘制检测到的人脸盒子)
  draw.drawDetections(canvas.value, resizedResult.box);
  drawBox(box, '')
  // video.value.pause()
  // //截取人脸图片
  const image = await cameraShoot(
    video.value,
    resizedResult.box.topLeft,
    resizedResult.box.width,
    resizedResult.box.height
  )
  if (!image) {
    drawBox(box, '识别失败')
    video.value.play()
    return detectFace()
  }
  const X= jgTime(lsDateTime,new Date())
  console.log('----',X,dialogVisible.value)
  // console.log(image)
  if(dialogVisible.value&&X>configData.value.face_push&&isworkTime(new Date())){
    lsDateTime=new Date()
    console.log(X,'上传阿里识别间隔')
    base64toFile(image)
  }
  return detectFace()
}
// 加载算法模型 文件存储在 public 文件夹下models文件夹。// 需要文件的话联系我
const init = async () => {
  await nets.ssdMobilenetv1.loadFromUri('./models')
}
/** @name 调用摄像头 */
const getUserMedia = (success: NavigatorUserMediaSuccessCallback, error: NavigatorUserMediaErrorCallback) => {
  const constraints = {
    audio:false,
    video: {
      width: 800,
      height: 500
    }
  }
  if (navigator.mediaDevices.getUserMedia) {
    // 最新的标准API
    console.log('sssdsdsd')
    navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error)
  } else if (navigator.webkitGetUserMedia) {
    // webkit核心浏览器
    navigator.webkitGetUserMedia(constraints, success, error)
  } else if (navigator.mozGetUserMedia) {
    // firfox浏览器
    navigator.mozGetUserMedia(constraints, success, error)
  } else if (navigator.getUserMedia) {
    // 旧版API
    navigator.getUserMedia(constraints, success, error)
  }
}
/** @name 截取快照 */
const cameraShoot = (video: HTMLVideoElement, startPoint: { x: number; y: number }, width: number, height: number) => {
  const canvas = document.createElement('canvas')
  canvas.width = video.videoWidth
  canvas.height = video.videoHeight
  canvas.getContext('2d')?.drawImage(video, 0, 0, canvas.width, canvas.height)
  const imgSrc = canvas?.toDataURL('image/png');
  return imgSrc
}
// 画盒子
const drawBox = (box: Box<any> | faceapi.IBoundingBox | faceapi.IRect, label: string) => {
  if (!canvas.value) return
  const context = canvas.value.getContext('2d')
  context?.clearRect(box.x, box.y, box.width, box.height)
  const drawBox = new draw.DrawBox(box, {
    label: label,
    boxColor:'#409EFF'
  })
  drawBox.draw(canvas.value)
}
// 停止
const handleStopVideo = () => {
  if (stream.value) {
    stream.value.getTracks().forEach((track: { stop: () => void; }) => {
      track.stop()
    })
  }
}
</script>
<style src="./index.css" />
<style lang="less" scoped>
@@ -774,25 +1053,26 @@
  justify-content: center;
  border-radius: 2px;
  .rWrapp {
    width: 500px;
    display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  // transform: rotateY(180deg);
  overflow: hidden;
  canvas {
    position: absolute;
    top: 0;
    width: 800px;
    height: 500px;
    margin: auto;
    // margin-top: 30px;
    position: relative;
    .myCanvas {
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 50%;
      width: 100%;
      height: 100%;
    }
    #myVideo {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      object-fit: cover;
    }
    border-radius: 20%;
  }
  video {
    object-fit: fill;
    width: 800px;
    height: 500px;
    border-radius: 20px;
  }
  }
  .status {
    //margin-top: 100px;