ll
liukangdong
2024-11-01 064128dfb784d9780aa4ac5dbd897c29d46a2666
admin/src/components/business/OperaMemberWindow.vue
@@ -54,7 +54,37 @@
          </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>
@@ -63,14 +93,26 @@
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 { upload } from '@/api/system/common'
export default {
  name: 'OperaCompanyWindow',
  extends: BaseOpera,
  components: { GlobalWindow, UploadAvatarImage, UploadFaceImg },
  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'
      },
@@ -119,6 +161,122 @@
    })
  },
  methods: {
    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.$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]