Newer
Older
securityFront / src / views / staff / staffEdit.vue
wangxitong on 20 Feb 2021 21 KB bug修改
<template>
  <div class="app-container">
    <el-form v-loading="formLoading" ref="dataForm" :label-position="labelPosition" :rules="rules" :model="personForm" class="main-form" label-width="120px">
      <el-row>
        <el-col :span="16">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="姓名" prop="name">
                <el-input v-model.trim="personForm.name" :disabled="isEditMode" clearable show-word-limit maxlength="10" type="text" placeholder="必填"/>
              </el-form-item>
            </el-col>
            <el-col :span="12" >
              <el-form-item label="身份证号" prop="idCard">
                <el-input v-model.trim="personForm.idCard" :disabled="isEditMode" clearable type="text" placeholder="身份证号"/>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12" >
              <el-form-item label="出生日期" prop="birthday">
                <el-date-picker
                  v-model="personForm.birthday"
                  :editable="false"
                  :disabled="isEditMode"
                  type="date"
                  style="width: 100%"
                  value-format="yyyy-MM-dd"
                  placeholder="选择出生日期"/>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="性别" prop="sex">
                <el-select v-model="personForm.sex" :disabled="isEditMode" placeholder="性别" clearable>
                  <el-option v-for="item in sexList" :key="item.value" :label="item.name" :value="item.value"/>
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="部门" prop="deptid">
                <el-select v-model="personForm.deptid" placeholder="单位/部门" filterable clearable>
                  <el-option v-for="item in deptList" :key="item.id" :label="item.name" :value="item.id"/>
                </el-select>
                <!--<dept-select v-model="personForm.deptid" :need-top="deptShowTop" :dept-show="true" placeholder="单位/部门"/>-->
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="联系电话" prop="phone">
                <el-input v-model.trim="personForm.phone" type="text" placeholder="非必填"/>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="住址" prop="address">
                <el-input v-model.trim="personForm.address" type="text" placeholder="非必填"/>
              </el-form-item>
            </el-col>
          </el-row>

          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="重点区域授权">
                <el-checkbox-group v-model="areas">
                  <el-checkbox v-for="item in keyAreaList" :label="item.value" :key="item.value" border>{{ item.name }}</el-checkbox>
                </el-checkbox-group>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row v-show="isKey" :gutter="20">
            <el-col :span="24">
              <el-form-item label="虹膜图片">
                <el-image
                  :src="personForm.irisData.rightImage!==''?personForm.irisData.rightImage:defaultIris"
                  fit="cover"
                  style="width: 192px; height: 128px"/>
                <el-image
                  :src="personForm.irisData.leftImage!==''?personForm.irisData.leftImage:defaultIris"
                  fit="cover"
                  style="width: 192px; height: 128px"/>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row v-show="isKey" :gutter="20">
            <el-col :span="24">
              <el-form-item label="虹膜质量">
                <span style="display:inline-block; width:192px; text-align: center">右眼评分:{{ personForm.irisData.rightIrisScore }}</span>
                <span style="display:inline-block; width:192px; text-align: center">左眼评分:{{ personForm.irisData.leftIrisScore }}</span>
              </el-form-item>
            </el-col>
          </el-row>
        </el-col>
        <el-col :span="6" :offset="2">
          <el-row>
            <div class="avatar">
              <el-image
                :src="photo!==''?photo:defaultPhoto"
                fit="cover"
                style="width: 130px; height: 175px"/>
            </div>
          </el-row>
          <el-row>
            <el-upload
              ref="upload"
              :before-upload="handleBeforeUpload"
              :http-request="uploadFile"
              :show-file-list="false"
              class="avatar-uploader"
              action="string"
              accept=".jpg,.jpeg,.png">
              <el-button type="primary">点击上传照片</el-button>
            </el-upload>
          </el-row>
          <el-row>
            <el-button type="primary" plain :disabled="canRead"  class="id-card-btn" @click="readIDCard">读取身份证</el-button>
          </el-row>
          <el-row>
            <el-button type="primary" plain class="id-card-btn" @click="readCamera">{{ btnCamera }}</el-button>
          </el-row>
        </el-col>
      </el-row>
    </el-form>
    <div style="height: 120px;">
      <el-row type="flex" justify="center">
        <el-col :span="15" style="text-align:center">
          <el-button v-show="isKey" type="primary" style="margin-left: 20px;" @click="registerIris"> 注册虹膜 </el-button>
          <el-button type="primary" style="margin-left: 20px;" @click="saveData"> 保存 </el-button>
        </el-col>
        <el-col :span="6" :offset="3">
          <video v-show="showVideo" width="200px" height="150px" style="margin-left: -8px"></video>
          <canvas v-show = "false" width="200px" height="150px"></canvas>
        </el-col>
      </el-row>
    </div>

    <capture-iris ref="captureIris" />
  </div>
</template>

<script>
import DeptSelect from '@/components/DeptSelect'
import { detailStaff, editPerson } from '@/api/staff'
import { getSexType } from '@/api/allDict'
import { getIrisAreaList } from '@/api/area'
import { getBirthdayByIdNO, getSexByIdNO } from '@/utils/dataAnalysis'
import CaptureIris from './captureIris'
import { getDeptTreeList } from '@/api/dept'
export default {
  name: 'StaffEdit',
  components: { CaptureIris, DeptSelect },
  data() {
    // 身份证号码校验
    const validateIDCard = (rule, value, callback) => {
      if (value !== '') {
        if ((/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/).test(value) === false) {
          callback(new Error('请输入合法的身份证号'))
        } else {
          callback()
        }
      } else {
        callback(new Error('身份证号不能为空'))
      }
    }

    return {
      canRead: false,
      deptList: [],
      btnCamera:'读取摄像头',
      showVideo: false,
      stream:'',
      isEditMode: false, // 是否为编辑模式,编辑模式部分字段不允许修改,且没有重置和虹膜注册功能
      isKey: false, // 是否重点区域授权人员
      reCaptureIris: '0', // 是否重新采集了虹膜
      personForm: {
        id: '', // 人员id
        idCard: '', // 身份证号
        name: '', // 姓名
        deptid: '', // 单位/部门
        sex: '', // 性别
        phone: '', // 联系电话
        birthday: '', // 出生日期
        photo: '',
        address: '', // 住址
        areaIds: '',
        irisData: {
          id: '', // 虹膜数据id
          leftImage: '', // 左眼虹膜图片
          leftIrisScore: '0', // 左眼虹膜图片质量分
          rightImage: '', // 右眼虹膜图片
          rightIrisScore: '0' // 右眼虹膜图片质量分
        }
      }, // 表单
      photo: '', // 图片路径
      defaultPhoto: require('@/assets/global_images/photo.png'), // 默认图片路径
      defaultIris: require('@/assets/global_images/iris.png'),
      fileList: [],
      imageList: [],
      sexList: [], // 性别列表
      areas: [], // 重点区域复选框对应值
      keyAreaList: [],
      rules: {
        name: [{ required: true, message: '姓名必填', trigger: ['blur', 'change'] }],
        deptid: [{ required: true, message: '单位/部门必选', trigger: 'change' }],
        idCard: [{ required: true, trigger: ['blur', 'change'], validator: validateIDCard }]
      },
      labelPosition: 'right',
      deptShowTop: true, // 权属单位下拉是否显示顶级
      deptShow: true,
      formLoading: false
    }
  },
  watch: {
    'personForm.idCard': function(val) {
      // if(val && )
      this.personForm.birthday = getBirthdayByIdNO(val)
      this.personForm.sex = getSexByIdNO(val)
    },
    'areas': function(val) {
      if (this.areas.length > 0) {
        this.personForm.areaIds = this.areas.toString()
        this.isKey = true
      } else {
        this.personForm.areaIds = ''
        this.isKey = false
      }
    }
  },
  mounted() {
    getDeptTreeList().then(response => {
      const list = response.data.list
      for (let i = 0; i < list.length; i++) {
        if (list[i].pid !== '-1' && list[i].pid !== '0') {
          this.deptList.push(list[i])
        }
      }
    })
    this.fetchSexType()// 获取性别列表
    this.fetchIrisRegions() // 获取虹膜设备关联区域的列表
  },
  activated() {
    if (this.$route.query && this.$route.query.type) {
      const type = this.$route.query.type
      if (type === 'create') {
        this.isEditMode = false // 不是编辑页面
      } else if (type === 'update') {
        this.isEditMode = true // 是编辑页面
        this.fetchData(this.$route.query.id)
      }
    }
  },
  methods: {
    // 获取性别
    fetchSexType() {
      getSexType().then(response => {
        this.sexList = response.data
      })
    },
    fetchIrisRegions() {
      getIrisAreaList().then(response => {
        this.keyAreaList = response.data
      })
    },
    readCamera() {
      if(this.btnCamera === '读取摄像头'){
        this.cameraImgFile()
      }else{
        this.getAPhoto()
      }
    },
    getAPhoto() {
      //绘制canvas图形
      let video = document.getElementsByTagName("video")[0]
      var canvas = document.getElementsByTagName('canvas')[0]
      var context = canvas.getContext('2d')
      context.clearRect(0, 0, context.width, context.height);
      context.drawImage(video, 0, 0,200,150);
      this.showVideo = false
      //把canvas图像转为img图片
      this.photo = canvas.toDataURL("image/png");
      var mediaStreamTrack =  this.stream.getTracks()[0];
      mediaStreamTrack.stop();
      this.btnCamera = '读取摄像头'
    },
    // 拍照上传获取video
    cameraImgFile() {
      let _this = this;

      // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }
      // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
      // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
      if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function(constraints) {
          // 首先,如果有getUserMedia的话,就获得它
          var getUserMedia =
            navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

          // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
          if (!getUserMedia) {
            return Promise.reject(
              new Error("getUserMedia is not implemented in this browser")
            );
          }
          // 否则,为老的navigator.getUserMedia方法包裹一个Promise
          return new Promise(function(resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject);
          });
        };
      }
      navigator.mediaDevices
        .getUserMedia({ video: true, audio: false })
        .then(function(stream) {
          _this.stream = stream;
          _this.videoShow = true;
          // 旧的浏览器可能没有srcObject
          _this.$nextTick(() => {
            let video = document.getElementsByTagName("video")[0]
            if ("srcObject" in video) {
              video.srcObject = stream;
            } else {
              // 防止在新的浏览器里使用它,应为它已经不再支持了
              video.src = window.URL.createObjectURL(stream);
            }
            _this.showVideo = true
            _this.btnCamera = '拍照'
            video.onloadedmetadata = function(e) {
              video.play();
            };
          });
        })
        .catch(function(err) {
          _this.videoShow = false;
          _this.$message.warning("未发现可拍照设备或出现其他错误!");
        });
    },
    fetchData(id) {
      this.formLoading = true
      detailStaff(id).then(response => {
        if (response.code === 200) {
          const personForm = response.data
          // 人员基本信息
          this.personForm = {
            id: personForm.id, // 人员id
            idCard: personForm.idCard, // 身份证号
            name: personForm.name, // 姓名
            phone: personForm.phone, // 联系电话
            deptid: personForm.deptid, // 单位/部门
            sex: personForm.sex + '', // 性别
            birthday: personForm.birthday, // 出生日期
            photo: personForm.photo,
            areaIds: personForm.areaIds,
            address: personForm.address, // 住址
            irisData: {
              id: '', // 虹膜数据id
              leftImage: '', // 左眼虹膜图片
              leftIrisScore: '0', // 左眼虹膜图片质量分
              rightImage: '', // 右眼虹膜图片
              rightIrisScore: '0' // 右眼虹膜图片质量分
            }
          }

          // 显示图片
          this.photo = personForm.photo

          // 重点区域授权
          if (personForm.areaIds !== '') {
            this.areas = personForm.areaIds.split(',')
          }

          // 如果有重点区域授权,则显示虹膜区域的数据
          if (personForm.irisData !== '') {
            this.isKey = true
            this.personForm.irisData = {
              id: personForm.irisData.id,
              leftImage: process.env.BASE_API + '/static/' + personForm.irisData.leftImage,
              rightImage: process.env.BASE_API + '/static/' + personForm.irisData.rightImage,
              leftIrisScore: personForm.irisData.leftIrisScore,
              rightIrisScore: personForm.irisData.rightIrisScore
            }
          } else {
            this.isKey = false
          }
        }

        this.formLoading = false
      })
    },
    readIDCard() {
      this.resetForm()
      this.canRead = true
      const that = this
      this.ws = that.$root.ws
      if (this.ws === null) {
        this.ws = new WebSocket(that.$root.wsURL)
        // 注册各类回调
        this.ws.onopen = function() {
          that.ws.send('ReadIdCard')
        }
        this.ws.onclose = function() {
          that.$message.info('与ICS连接断开')
          that.$root.ws = null
        }
        this.ws.onerror = function() {
          that.$message.error('与ICS通信发生错误')
        }
        that.$root.ws = this.ws
      } else {
        this.ws.send('ReadIdCard')
      }
      this.ws.onmessage = function(receiveMsg) {
        that.canRead = false
        const data = JSON.parse(receiveMsg.data)
        if (data !== '' && data.message !== 'fail') {
          that.personForm.idCard = data.IdCardNo
          that.personForm.name = data.Name
          that.personForm.sex = parseInt(data.Sex)
          var birth = data.Birthday
          that.personForm.birthday = birth.substring(0, 3) + '-' + birth.substring(4, 5) + '-' + birth.substring(6, 7)
          that.photo = data.Photo.replace('bmp', 'png')
          that.personForm.address = data.Address
        } else {
          that.$message.warning('读卡失败')
        }
      }
    },
    // 重置表单
    resetForm() {
      this.personForm = {
        idCard: '', // 身份证号
        name: '', // 姓名
        deptid: '', // 单位/部门
        phone: '', // 联系电话
        sex: '', // 性别
        birthday: '', // 出生日期
        photo: '',
        address: '', // 住址
        irisData: {
          id: '', // 虹膜数据id
          leftImage: '', // 左眼虹膜图片
          leftIrisScore: '0', // 左眼虹膜图片质量分
          rightImage: '', // 右眼虹膜图片
          rightIrisScore: '0' // 右眼虹膜图片质量分
        }
      }
      this.photo = ''
      this.imageList = []
      this.fileList = []
      this.areas = []

      // 清除验证
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    // 保存数据
    saveData: function() {
      // 照片不为空则对照片进行处理
      if (this.photo !== '') {
        if (this.photo.startsWith('http')) { // 上传的普通图片,去掉static头
          let index = this.photo.indexOf('/static/')
          if (index !== -1) {
            index += 8
          }
          this.personForm.photo = this.photo.substring(index)
        } else if (this.photo.startsWith('data:image')) { // 读卡器读的base64图片,直接传编码
          this.personForm.photo = this.photo
        }
      }
      // 没有重新采集虹膜,则将irisData置空
      if (this.reCaptureIris === '0') {
        this.personForm.irisData = ''
      }

      // 如果重点区域为空,则将irisData置空
      if (this.areas.length === 0) {
        this.personForm.irisData = ''
      }

      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          if (this.isEditMode === true) {
            editPerson(this.personForm).then(response => {
              if (response.code === 200) {
                this.$message.success(response.message)
                this.$router.replace({ path: '/' + this.$store.getters.currentSystem.code + '/staff/list' })
              } else {
                this.$message.error(response.message)
                this.btnLoading = false
              }
            }).catch(() => {
              this.$message.error('保存失败')
            })
          }
        }
      })
    },
    // 注册虹膜
    registerIris() {
      // 已经填写了基本信息
      if (this.personForm.name !== '' && this.personForm.idCard !== '') {
        const data = {
          name: this.personForm.name,
          idCard: this.personForm.idCard
        }
        this.$refs.captureIris.initDialog(true, data, '0') // 编辑人员时采集虹膜
      } else {
        this.$message.warning('请先填写用户基本信息')
      }
    },
    // 图片上传
    uploadFile(file) {
      console.log('uploadFile:' + file.file.name)
      // 转base64
      this.getBase64(file.file).then(resBase64 => {
        this.photo = 'data:image/png;base64,' + resBase64.split(',')[1] // 直接拿到base64信息
        console.log(this.photo)
      })
    },
    // 上传前判断文件格式及大小
    handleBeforeUpload(file) {
      const isJPG = (file.type === 'image/jpeg') || (file.type === 'image/png')
      let res = true
      console.log(file.size)
      const isLt2M = file.size / 1024 < 200
      if (!isJPG) {
        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
        res = false
      }
      if (!isLt2M) {
        this.$message.error('上传图片大小不能超过 200KB!')
        res = false
      }
      return res
    },
    // 上传成功后回显
    handleSuccess(response, file) {
      console.log('handleSuccess')
      const base_url = process.env.BASE_API + '/static/'
      if (response.code === 200) {
        this.photo = base_url + response.data
      } else {
        this.$message.warning(response.message)
      }
    },
    getBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        let fileResult = ''
        reader.readAsDataURL(file)
        // 开始转
        reader.onload = function() {
          fileResult = reader.result
        }
        // 转 失败
        reader.onerror = function(error) {
          reject(error)
        }
        // 转 结束  咱就 resolve 出去
        reader.onloadend = function() {
          resolve(fileResult)
        }
      })
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" >
  .hide .el-upload--picture-card {
    display: none;
  }
  .main-form{
    margin: 0px 30px;
    margin-top: 20px;
    padding: 10px;
    overflow: auto;
  }
  .el-dialog{
    width:700px
  }
  .el-select{
    width: 100%;
  }
  .line{
    width: 50px;
    margin-left: 5px;
  }
  .hide .el-upload-–picture-card{
    display: none;
  }
  .imgBox{
    width: 100%;
    text-align: center;
  }
  .avatar-uploader .el-upload {
    margin-left: 12px;
    margin-top: 10px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 238px;
    line-height: 238px;
    text-align: center;
  }
  .avatar {
    margin: 10px;
    display: block;
  }
  .id-card-btn{
    width:126px;
    margin-left: 12px;
    margin-top: 20px;
  }
</style>