<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>