【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>
相关推荐
遇到困难睡大觉哈哈6 小时前
Harmony os 静态卡片(ArkTS + FormLink)详细介绍
前端·microsoft·harmonyos·鸿蒙
用户47949283569156 小时前
Bun 卖身 Anthropic!尤雨溪神吐槽:OpenAI 你需要工具链吗?
前端·openai·bun
p***43486 小时前
前端在移动端中的网络请求优化
前端
g***B7386 小时前
前端在移动端中的Ionic
前端
大猩猩X7 小时前
vxe-gantt 甘特图使用右键菜单
vue.js·vxe-table·vxe-ui·vxe-gantt
拿破轮7 小时前
使用通义灵码解决复杂正则表达式替换字符串的问题.
java·服务器·前端
whltaoin7 小时前
【 Web认证 】Cookie、Session 与 JWT Token:Web 认证机制的原理、实现与对比
前端·web·jwt·cookie·session·认证机制
Aerelin7 小时前
爬虫playwright入门讲解
前端·javascript·html·playwright
笙年7 小时前
JavaScript Promise,包括构造函数、对象方法和类方法
开发语言·javascript·ecmascript
桜吹雪7 小时前
LangChain.js/DeepAgents可观测性
javascript·人工智能