|  |  |  | 
|---|
|  |  |  | 注:仅支持选择 【{{ companyType === 0 ? '相关方组织' : '内部组织' }}】 | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | <el-form-item label="选择岗位:" prop="positionId" > | 
|---|
|  |  |  | <el-form-item label="选择岗位:" prop="positionId"> | 
|---|
|  |  |  | <el-select v-model="form.positionId" clearable filterable placeholder="请选择"> | 
|---|
|  |  |  | <el-option v-for="item in positionList" :key="item.id" :label="item.name" :value="item.id"> | 
|---|
|  |  |  | </el-option> | 
|---|
|  |  |  | 
|---|
|  |  |  | <el-input v-model="form.code" placeholder="请输入员工工号" v-trim /> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | <el-form-item label="入职日期" prop="jobDate"> | 
|---|
|  |  |  | <el-date-picker | 
|---|
|  |  |  | v-model="form.jobDate" | 
|---|
|  |  |  | value-format="yyyy-MM-dd" | 
|---|
|  |  |  | type="date"> | 
|---|
|  |  |  | <el-date-picker v-model="form.jobDate" value-format="yyyy-MM-dd" type="date"> | 
|---|
|  |  |  | </el-date-picker> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | <el-form-item label="是否党员" prop="isDangyuan"> | 
|---|
|  |  |  | <el-radio-group v-model="form.radio" @input="isDangyuan"> | 
|---|
|  |  |  | <el-radio :label="0">非党员</el-radio> | 
|---|
|  |  |  | <el-radio :label="1">党员</el-radio> | 
|---|
|  |  |  | </el-radio-group> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | <!--      <el-form-item label="是否党员" prop="isDangyuan"> | 
|---|
|  |  |  | <el-radio-group v-model="form.isDangyuan"> | 
|---|
|  |  |  | <el-radio :label="0">非党员</el-radio> | 
|---|
|  |  |  | <el-radio :label="1">党员</el-radio> | 
|---|
|  |  |  | </el-radio-group> | 
|---|
|  |  |  | </el-form-item>--> | 
|---|
|  |  |  | <el-form-item label="人脸照片" prop="faceImgFull"> | 
|---|
|  |  |  | <div class="upload_wrap"> | 
|---|
|  |  |  | <UploadFaceImg :file="{ 'imgurlfull': form.faceImgFull, 'imgurl': form.faceImg }" :uploadData="uploadData" | 
|---|
|  |  |  | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | <el-form-item> | 
|---|
|  |  |  | <div><el-button type="primary" @click="openCamera">采集</el-button></div> | 
|---|
|  |  |  | </el-form-item> | 
|---|
|  |  |  | </el-form> | 
|---|
|  |  |  | <!--  --> | 
|---|
|  |  |  | <el-dialog title="拍摄" :visible.sync="paisheModal" width="760px" :close-on-click-modal="false" | 
|---|
|  |  |  | :close-on-press-escape="false" append-to-body @close="closeCamera"> | 
|---|
|  |  |  | <video v-show="isShowCamera" id="videoCamera" :width="videoWidth" :height="videoHeight" /> | 
|---|
|  |  |  | <canvas v-show="!isShowCamera" id="canvasCamera" style="display: none" :width="videoWidth" | 
|---|
|  |  |  | :height="videoHeight" /> | 
|---|
|  |  |  | <span slot="footer"> | 
|---|
|  |  |  | <div> | 
|---|
|  |  |  | <el-button @click="closeCamera">取消</el-button> | 
|---|
|  |  |  | <el-button v-show="blobFileCamera" type="primary" @click="resetCamera">重拍</el-button> | 
|---|
|  |  |  | <el-button v-show="blobFileCamera" :loading="cameraLoading" type="primary" | 
|---|
|  |  |  | @click="enterCamera">开始裁剪</el-button> | 
|---|
|  |  |  | <el-button v-show="!blobFileCamera" type="primary" @click="setImage">拍摄</el-button> | 
|---|
|  |  |  | </div> | 
|---|
|  |  |  | </span> | 
|---|
|  |  |  | </el-dialog> | 
|---|
|  |  |  | <!--  --> | 
|---|
|  |  |  | <el-dialog append-to-body :close-on-click-modal="false" title="上传图片" :visible.sync="isShowCropper" width="1000px" | 
|---|
|  |  |  | class="icon-dialog-wrapper dialong-com-style"> | 
|---|
|  |  |  | <ImageCropper ref="iconShot" v-if="isShowCropper" :imgSrc="blobFileCamera"> | 
|---|
|  |  |  | </ImageCropper> | 
|---|
|  |  |  | <span slot="footer" class="dialog-footer"> | 
|---|
|  |  |  | <el-button v-if="loading">取 消</el-button> | 
|---|
|  |  |  | <el-button v-else @click="isShowCropper = false">取 消</el-button> | 
|---|
|  |  |  | <el-button :loading="loading" type="primary" @click="uploadIcon">确 定</el-button> | 
|---|
|  |  |  | </span> | 
|---|
|  |  |  | </el-dialog> | 
|---|
|  |  |  | </GlobalWindow> | 
|---|
|  |  |  | </template> | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | import GlobalWindow from '@/components/common/GlobalWindow' | 
|---|
|  |  |  | import UploadAvatarImage from '@/components/common/UploadAvatarImage' | 
|---|
|  |  |  | import UploadFaceImg from '@/components/common/UploadFaceImg' | 
|---|
|  |  |  | import ImageCropper from '@/components/common/ImageCropper' | 
|---|
|  |  |  | import { checkMobile, validIdCardNo, validIdCardNoNew } from '@/utils/form' | 
|---|
|  |  |  | import { allList   } from '@/api/business/position' | 
|---|
|  |  |  | import { allList } from '@/api/business/position' | 
|---|
|  |  |  | import { upload } from '@/api/system/common' | 
|---|
|  |  |  | export default { | 
|---|
|  |  |  | name: 'OperaCompanyWindow', | 
|---|
|  |  |  | extends: BaseOpera, | 
|---|
|  |  |  | components: { GlobalWindow, UploadAvatarImage, UploadFaceImg }, | 
|---|
|  |  |  | data () { | 
|---|
|  |  |  | components: { GlobalWindow, UploadAvatarImage, UploadFaceImg, ImageCropper }, | 
|---|
|  |  |  | data() { | 
|---|
|  |  |  | return { | 
|---|
|  |  |  | isShowCamera: false, | 
|---|
|  |  |  | paisheModal: false, | 
|---|
|  |  |  | cameraLoading: false, | 
|---|
|  |  |  | videoWidth: 700, | 
|---|
|  |  |  | videoHeight: 525, | 
|---|
|  |  |  | mediaStreamCamera: '', | 
|---|
|  |  |  | blobFileCamera: '', | 
|---|
|  |  |  | isShowCropper: false, | 
|---|
|  |  |  | loading: false, | 
|---|
|  |  |  | // 以上是拍摄 | 
|---|
|  |  |  | uploadData: { | 
|---|
|  |  |  | folder: 'member' | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | created () { | 
|---|
|  |  |  | created() { | 
|---|
|  |  |  | this.config({ | 
|---|
|  |  |  | api: '/business/member.js', | 
|---|
|  |  |  | 'field.id': 'id' | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | methods: { | 
|---|
|  |  |  | handleChangeCompany (value) { | 
|---|
|  |  |  | openCamera() { | 
|---|
|  |  |  | this.paisheModal = true | 
|---|
|  |  |  | this.isShowCamera = true | 
|---|
|  |  |  | const that = this | 
|---|
|  |  |  | this.$nextTick(() => { | 
|---|
|  |  |  | var mediaOpts = { audio: false, video: true } | 
|---|
|  |  |  | navigator.mediaDevices | 
|---|
|  |  |  | .getUserMedia(mediaOpts) | 
|---|
|  |  |  | .then(function (stream) { | 
|---|
|  |  |  | that.mediaStreamCamera = stream | 
|---|
|  |  |  | const video = document.querySelector('#videoCamera') | 
|---|
|  |  |  | if ('srcObject' in video) { | 
|---|
|  |  |  | video.srcObject = stream | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | video.src = | 
|---|
|  |  |  | (window.URL && window.URL.createObjectURL(stream)) || stream | 
|---|
|  |  |  | } | 
|---|
|  |  |  | video.play() | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | .catch(function (err) { | 
|---|
|  |  |  | console.log(err) | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | // 重拍 | 
|---|
|  |  |  | resetCamera() { | 
|---|
|  |  |  | this.isShowCamera = true | 
|---|
|  |  |  | this.blobFileCamera = '' | 
|---|
|  |  |  | this.openCamera() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | // 关闭相机 | 
|---|
|  |  |  | closeCamera() { | 
|---|
|  |  |  | this.mediaStreamCamera.getVideoTracks().forEach(function (track) { | 
|---|
|  |  |  | track.stop() | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | this.paisheModal = false | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | // 点击拍摄 | 
|---|
|  |  |  | setImage() { | 
|---|
|  |  |  | const that = this | 
|---|
|  |  |  | that.isShowCamera = false | 
|---|
|  |  |  | const video = document.querySelector('#videoCamera') | 
|---|
|  |  |  | const canvas = document.querySelector('#canvasCamera') | 
|---|
|  |  |  | canvas | 
|---|
|  |  |  | .getContext('2d') | 
|---|
|  |  |  | .drawImage(video, 0, 0, that.videoWidth, that.videoHeight) | 
|---|
|  |  |  | this.mediaStreamCamera.getVideoTracks().forEach(function (track) { | 
|---|
|  |  |  | track.stop() | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | const dataurl = canvas.toDataURL('image/jpg') | 
|---|
|  |  |  | // this.blobFileCamera = that.base64ToFile(dataurl, 'camera') | 
|---|
|  |  |  | this.blobFileCamera = dataurl | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | // 确认拍摄 | 
|---|
|  |  |  | enterCamera() { | 
|---|
|  |  |  | this.isShowCropper = true | 
|---|
|  |  |  | this.paisheModal = false | 
|---|
|  |  |  | this.isShowCamera = true | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | uploadIcon () { | 
|---|
|  |  |  | // 获取裁剪后的图片 | 
|---|
|  |  |  | this.$refs.iconShot.getImagecropper().getCropBlob((fileData) => { // 获取当前裁剪好的数据 | 
|---|
|  |  |  | // 注此时的data是一个Blob数据,部分接口接收的是File转化的FormData数据 | 
|---|
|  |  |  | console.log(fileData) | 
|---|
|  |  |  | const formData = new FormData() | 
|---|
|  |  |  |  | 
|---|
|  |  |  | formData.append('folder', 'member') | 
|---|
|  |  |  | formData.append( | 
|---|
|  |  |  | 'file', | 
|---|
|  |  |  | fileData | 
|---|
|  |  |  | ) | 
|---|
|  |  |  | this.loading = true | 
|---|
|  |  |  | upload(formData).then(res => { | 
|---|
|  |  |  | this.loading = false | 
|---|
|  |  |  | console.log(res) | 
|---|
|  |  |  | // this.file.imgurl = res.imgaddr | 
|---|
|  |  |  | // this.file.imgurlfull = res.url | 
|---|
|  |  |  | this.$message.success('上传成功') | 
|---|
|  |  |  | // this.imageSrc = res.url | 
|---|
|  |  |  | // this.updateImg = false | 
|---|
|  |  |  | this.form.faceImg = res.imgaddr | 
|---|
|  |  |  | this.form.faceImgFull = res.url | 
|---|
|  |  |  | this.isShowCropper = false | 
|---|
|  |  |  | // this.$emit('uploadSuccess', { imgurl: res.imgaddr, imgurlfull: res.url, name: res.originname }) | 
|---|
|  |  |  | // this.$emit('uploadEnd') | 
|---|
|  |  |  | }, () => { | 
|---|
|  |  |  | this.loading = false | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | base64ToFile(base64, fileName) { | 
|---|
|  |  |  | // 将base64按照 , 进行分割 将前缀  与后续内容分隔开 | 
|---|
|  |  |  | const data = base64.split(',') | 
|---|
|  |  |  | // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) | 
|---|
|  |  |  | const type = data[0].match(/:(.*?);/)[1] | 
|---|
|  |  |  | // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) | 
|---|
|  |  |  | const suffix = type.split('/')[1] | 
|---|
|  |  |  | // 使用atob()对base64数据进行解码  结果是一个文件数据流 以字符串的格式输出 | 
|---|
|  |  |  | const bstr = window.atob(data[1]) | 
|---|
|  |  |  | // 获取解码结果字符串的长度 | 
|---|
|  |  |  | let n = bstr.length | 
|---|
|  |  |  | // 根据解码结果字符串的长度创建一个等长的整形数字数组 | 
|---|
|  |  |  | // 但在创建时 所有元素初始值都为 0 | 
|---|
|  |  |  | const u8arr = new Uint8Array(n) | 
|---|
|  |  |  | // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 | 
|---|
|  |  |  | while (n--) { | 
|---|
|  |  |  | // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 | 
|---|
|  |  |  | u8arr[n] = bstr.charCodeAt(n) | 
|---|
|  |  |  | } | 
|---|
|  |  |  | // 利用构造函数创建File文件对象 | 
|---|
|  |  |  | // new File(bits, name, options) | 
|---|
|  |  |  | const file = new File([u8arr], `${fileName}.${suffix}`, { | 
|---|
|  |  |  | type: type | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | // 将File文件对象返回给方法的调用者 | 
|---|
|  |  |  | return file | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | handleChangeCompany(value) { | 
|---|
|  |  |  | if (this.form.company && this.form.company.length > 1) { | 
|---|
|  |  |  | this.form.companyId = this.form.company[this.form.company.length - 1] | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | * @title 窗口标题 | 
|---|
|  |  |  | * @target 编辑的对象 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | open (title, target, depart, companyType) { | 
|---|
|  |  |  | open(title, target, depart, companyType) { | 
|---|
|  |  |  | this.title = title | 
|---|
|  |  |  | this.department = depart | 
|---|
|  |  |  | this.visible = true | 
|---|
|  |  |  | this.form = { | 
|---|
|  |  |  | id: null, | 
|---|
|  |  |  | name: '', | 
|---|
|  |  |  | type: '', | 
|---|
|  |  |  | company: [], | 
|---|
|  |  |  | code: '', | 
|---|
|  |  |  | idcardNo: '', | 
|---|
|  |  |  | idcardNoNew: '', | 
|---|
|  |  |  | linkName: '', | 
|---|
|  |  |  | idcardDecode: '', | 
|---|
|  |  |  | companyId: null, | 
|---|
|  |  |  | idcardType: 0, | 
|---|
|  |  |  | phone: '', | 
|---|
|  |  |  | faceImg: '', | 
|---|
|  |  |  | jobDate: null, | 
|---|
|  |  |  | isDangyuan: 0, | 
|---|
|  |  |  | positionId: null, | 
|---|
|  |  |  | faceImgFull: '' | 
|---|
|  |  |  | } | 
|---|
|  |  |  | this.companyType = companyType | 
|---|
|  |  |  | this.positionList() | 
|---|
|  |  |  | this.getPositionList() | 
|---|
|  |  |  | // 新建 | 
|---|
|  |  |  | if (target == null) { | 
|---|
|  |  |  | this.$nextTick(() => { | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | getPositionList () { | 
|---|
|  |  |  | getPositionList() { | 
|---|
|  |  |  | allList({}) | 
|---|
|  |  |  | .then(res => { | 
|---|
|  |  |  | this.positionList = res | 
|---|
|  |  |  | }) | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | // 上传图片 | 
|---|
|  |  |  | uploadAvatarSuccess (file) { | 
|---|
|  |  |  | uploadAvatarSuccess(file) { | 
|---|
|  |  |  | this.form.faceImg = file.imgurl | 
|---|
|  |  |  | this.form.faceImgFull = file.imgurlfull | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | </script> | 
|---|
|  |  |  | <style lang="scss" scoped> | 
|---|
|  |  |  | .upload_wrap{ | 
|---|
|  |  |  | .upload_wrap { | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | align-items: center; | 
|---|
|  |  |  | .avatar-uploader{ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .avatar-uploader { | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | align-items: center; | 
|---|
|  |  |  | justify-content: center; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | ::v-deep .avatar{ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | ::v-deep .avatar { | 
|---|
|  |  |  | max-width: 90px; | 
|---|
|  |  |  | max-height: 90px; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | .content{ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | .content { | 
|---|
|  |  |  | display: flex; | 
|---|
|  |  |  | flex-direction: column; | 
|---|
|  |  |  | justify-content: center; | 
|---|