【sgMobileUploadTypeSelect】自定义组件:从底部弹出选择上传图片文件的方式【1、上传本地文件,2、拍摄上传】

sgMobileUploadTypeSelect.vue

html 复制代码
<template>
  <!-- 选择是直接上传手机文件还是拍摄上传 -->
  <div :class="$options.name" :show="visible">
    <div class="bg" @click="visible = false"></div>
    <div class="container">
      <div class="close" @click="visible = false">
        <i class="el-icon-close" />
      </div>

      <div class="upload-types">
        <div class="item" @click="(uploadBtn || {}).click()">
          <i class="el-icon-upload" />
        </div>
        <div class="item" @click="scan">
          <i class="el-icon-camera" />
        </div>
      </div>
    </div>
    <sgUploadCameraImage ref="sgUploadCameraImage" @change="getUploadFiles_scan" />
    <el-upload
      ref="upload"
      :accept="``"
      :action="`#`"
      :auto-upload="false"
      :multiple="true"
      :on-change="getUploadFiles_upload"
      :show-file-list="false"
      :dragenter="isDragenter"
      :drag="false"
    />
    <!-- 如果drag=true,accept必须为具体的格式,否则无法监听on-change -->
  </div>
</template>
<script>
import sgUploadCameraImage from "@/vue/components/admin/sgUploadCameraImage";

export default {
  name: `sgMobileUploadTypeSelect`,
  components: { sgUploadCameraImage },
  data() {
    return {
      visible: false,
      form: {},
      change: null,

      uploadBtn: null, //上传触发按钮
      isDragenter: false, //是否拖拽进入
    };
  },

  props: [`value`, `data`],

  watch: {
    value: {
      handler(d) {
        this.visible = d;
      },
      deep: true,
      immediate: true,
    },
    visible(d) {
      this.$emit("input", d);
    },
    data: {
      handler(newValue, oldValue) {
        //console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
        if (Object.keys(newValue || {}).length) {
          this.form = this.$g.deepCopy(newValue);
          this.$g.cF2CP(`disabled`, this);
          this.$g.cF2CP(`change`, this);
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  mounted() {
    this.uploadBtn = this.$refs.upload.$children[0].$refs.input;
  },

  methods: {
    // -------------------------------------
    // 唤起摄像头拍照扫描上传
    scan(d) {
      this.$refs.sgUploadCameraImage.scan();
    },
    // 获取拍照图片文件
    getUploadFiles_scan(file) {
      this.$emit(`change`, file);
      this.change && this.change(file);
      this.visible = false;
    },
    // -------------------------------------
    // 获取上传文件----------------------------------------
    getUploadFiles_upload(file) {
      file = file.raw;
      this.$emit(`change`, file);
      this.change && this.change(file);
      this.visible = false;
    },
  },
};
</script>
<style lang="scss" scoped>
.sgMobileUploadTypeSelect {
  position: fixed;
  width: 100vw;
  height: 100vh;
  left: 0;
  bottom: 0;
  pointer-events: none;
  transition: 0.2s;
  z-index: 1;
  .bg {
    width: 100%;
    height: 100%;
    background-color: #00000099;
    opacity: 0;
    transition: 0.2s;
  }
  .container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    transition: 0.2s;
    position: absolute;
    transform: translateY(100%);
    width: 100%;
    left: 0;
    bottom: 0;
    background-color: white;
    height: 200px;
    border-radius: 16px 16px 0 0;
    box-shadow: 0 11px 33px 0 #00000011;
    box-sizing: border-box;
    padding: 20px;
    //   padding-top: 60px;
    .close {
      position: absolute;
      right: 20px;
      top: 20px;
      z-index: 1;
      color: #666;
      i {
        font-size: 20px;
      }
    }

    .upload-types {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-evenly;
      .item {
        width: 100px;
        height: 100px;
        /*禁止选中文本*/
        user-select: none;
        background-color: #eff2f7;
        color: #8896b3;
        font-size: 40px;
        display: flex;
        justify-content: center;
        align-items: center;
        border-radius: 8px;
        box-sizing: border-box;
        &:active {
          color: black;
          background-color: #c6d1de;
        }
      }
    }
  }

  &[show] {
    pointer-events: auto;
    .bg {
      opacity: 1;
    }
    .container {
      transform: translateY(0%);
    }
  }
}
</style>

demo

html 复制代码
<!-- 选择上传方式 -->
<sgMobileUploadTypeSelect
  :data="data_sgMobileUploadTypeSelect"
  v-model="show_sgMobileUploadTypeSelect"
/>


import sgMobileUploadTypeSelect from "@/vue/components/admin/sgMobileUploadTypeSelect";


rw_sgMobileUploadTypeSelect({ w = true, d = {} } = {}) {
  this.data_sgMobileUploadTypeSelect = this.$g.deepCopy(d);
  this.data_sgMobileUploadTypeSelect.disabled = !w;
  this.show_sgMobileUploadTypeSelect = true;
},



<div
  class="upload-btn"
  @click="rw_sgMobileUploadTypeSelect({ d: { change: getUploadFiles } })"
>
  <i class="el-icon-camera" />
</div>
相关推荐
Mike_jia2 小时前
Checkmate:自建监控新标杆!开源替代Zabbix的轻量级方案实战
前端
fury_1232 小时前
tsfile.raw提示
java·前端·javascript
喝拿铁写前端2 小时前
从面条代码到抽象能力:一个小表单场景里的前端成长四阶段
前端·设计模式·架构
LXA08092 小时前
Vue 3中使用JSX
前端·javascript·vue.js
执携2 小时前
Vue Router (历史模式)
前端·javascript·vue.js
是梦终空2 小时前
vue下载依赖报错npm ERR node-sass@4.14.1 postinstall: `node scripts/build.js`的解决方法
javascript·npm·vue·node-sass·vue依赖
依米_2 小时前
一文带你剖析 Promise.then all 实现原理,状态机、发布订阅模式完美实现异步编程
javascript·设计模式
陈陈小白2 小时前
npm run dev报错Error: listen EADDRINUSE: address already in use :::8090
前端·npm·node.js·vue