基于vue3的elementPlus的上传图片组件的二次封装

上传图片经常需要用到,特此写下一个组件。

<template>
  <div>
    <el-upload multiple :action="uploadImgUrl" ref="uploadRef" :disabled="disabled" list-type="picture-card"
      :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError"
      :on-exceed="handleExceed" name="file" :on-remove="handleRemove" :show-file-list="true" :headers="headers"
      v-model:file-list="fileArr" :on-preview="handlePictureCardPreview" :class="{ disabled: fileComputed }">
      <el-icon class="avatar-uploader-icon">
        <plus />
      </el-icon>
    </el-upload>
    <!-- 上传提示 -->
    <div class="el-upload__tip" v-if="showTip">
      请上传
      <template v-if="fileSize">
        大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
      </template>
      <template v-if="fileType">
        格式为 <b style="color: #f56c6c">{{ fileType }}</b>
      </template>
      的图片
    </div>

    <el-dialog v-model="dialogVisible" title="预览" width="800px" append-to-body>
      <img :src="dialogImageUrl" style="display: block; width: 100%; margin: 0 auto" />
    </el-dialog>
  </div>
</template>
 
<script setup>
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue';
import { getToken } from '@/utils/token';
const props = defineProps({
  // 数量限制
  limit: {
    type: Number,
    default: 1,
  },
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default: 10,
  },
  // 文件类型, 例如'png', 'jpg', 'jpeg',字符串,英文逗号隔开
  fileType: {
    type: String,
    default: ".png,.jpg,.jpeg",
  },
  // 上传的请求头部
  headers: {
    required: false,
    default: { Authorization: `Bearer ${getToken()}` },
  },
  // 请求的url
  uploadImgUrl: {
    type: String,
    default: `${import.meta.env.VITE_APP_BASE_API}/file/upload`
  },
  // 是否显示提示
  isShowTip: {
    type: Boolean,
    default: true,
  },
  // 图片数组
  fileList: {
    type:Array,
    required: false
  },
  // 照片墙盒子的宽度
  fileWidth: {
    type: String,
    default: '146px'
  },
  // 照片墙盒子的高度
  fileHeight: {
    type: String,
    default: '146px'
  },
  disabled: {
    type: Boolean,
    default: false,
  }
})

const emit = defineEmits(['update:fileList'])

const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize));
const dialogVisible = ref(false)
const dialogImageUrl = ref('')
const fileArr = ref([])

// 上传超过数量限制,显示上传按钮
const fileComputed = computed(() => fileArr.value?.length == props.limit)

onMounted(() => {
  fileArr.value = props.fileList
})

watch(() => props.fileList,
  (newNum, oldNum) => {
    fileArr.value = newNum
  },
  {
    // 开启深度监听
    deep: true,
  })
// 上传前检验文件类型和文件大小
const handleBeforeUpload = (file) => {
  // 检验文件类型
  let arr = props.fileType.split(',')
  if (arr.length) {
    let str = '.' + file.name.match(/\.([^.]+)$/)[1].toLowerCase()  //匹配格式
    const isTypeOk = arr.some((type) => {
      if (str.indexOf(type) > -1) return true
      return false
    })
    if (!isTypeOk) {
      ElMessage.error(`文件格式不正确, 请上传${props.fileType}格式的图片!`)
      return false
    }

  }

  // 检验文件大小
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      ElMessage.error(`上传文件大小不能超过 ${props.fileSize} MB!`)
      return false;
    }
  }
  return true
}

// 上传失败的提示
const handleUploadError = () => {
  ElMessage.error(`图片上传失败!`)
}

// 上传超过限制
const handleExceed = () => {
  ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`)
}

// 上传成功的回调
const handleUploadSuccess = (response, file, fileList) => {
  emit('update:fileList', fileList)

}

// 删除图片的回调
const handleRemove = (file, fileList) => {
  emit('update:fileList', fileList)
}

// 预览图片的回调
const handlePictureCardPreview = (file) => {
  dialogImageUrl.value = file.url;
  dialogVisible.value = true;
}
const uploadRef = ref(null)
defineExpose({
  uploadRef,
  fileArr
})
</script>
 
<style lang="scss" scoped>
.disabled :deep(.el-upload--picture-card) {
  display: none
}

:deep(.el-upload-list__item-actions) {
  width: v-bind('props.fileWidth') !important;
  height: v-bind('props.fileHeight') !important;
}

:deep(.el-upload--picture-card) {
  width: v-bind('props.fileWidth') !important;
  height: v-bind('props.fileHeight') !important;
}

:deep(.el-upload-list__item) {
  width: v-bind('props.fileWidth') !important;
  height: v-bind('props.fileHeight') !important;
}
</style>

以上props中url必传,其他像大小,数量,文件类型,headers,fileList(回显数组), 照片墙盒子的宽高根据需要传入即可。

举例:

<template>
  <div style="margin: 15px;">

    <el-button type="primary" @click="open = true">新增</el-button>

    <!-- dialogue对话框 -->
    <el-dialog v-model="open" title="上传" align-center width="800px" @close="cancelBtn">
      <el-form :model="dialogueForm" label-width="100px">
        <el-form-item label="图片:">
          <imgUpload :limit="2"  ref="imgUploadRef" :fileSize="100" :isShowTip="false" :fileList="showImg" @update:fileList="successUploadBtn"
            fileWidth="100px" fileHeight="100px"></imgUpload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancelBtn">取消</el-button>
          <el-button type="primary" @click="confirmBtn">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import imgUpload from '@/Components/imgUpload.vue'
const open = ref(false)
const showImg = ref([]) //有编辑按钮回显图片的,只有新增时候fileList可无需传
const imgUploadRef = ref({})
const dialogueForm = ref({})

//上传成功,删除都会调用这个函数,可将要提交的数据在这里操作,如imgPath为接口所传的图片地址
const successUploadBtn = (val) => {
  //可以打印一下val,看看哪些是要接口所需要的数据
  console.log(val, '瞅瞅')
  if (val && val[0] && val[0].response) {
    dialogueForm.value.imgPath = val[0].response.data.url
  } else {
    dialogueForm.value.imgPath = ''
  }
}

const cancelBtn = () => {
  //清空已上传的文件列表
  imgUploadRef.value.uploadRef.clearFiles()
  //关闭弹窗
  open.value = false
}
const confirmBtn = () => {
  /**
   * 调接口 。。。。接口(传参) 。。。uploadApi(dialogueForm.value.imgPath)
   */
  //清空已上传的文件列表
  imgUploadRef.value.uploadRef.clearFiles()
  //关闭弹窗
  open.value = false
}

</script>

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为你提供一些指导和建议。首先,你需要安装 Vue 3 和 Element Plus 的依赖。可以使用以下命令进行安装: ``` npm install vue@next npm install element-plus ``` 然后,你可以创建一个名为 `Cron` 的 Vue 组件,该组件将用于呈现 Cron 表达式编辑器。在组件中,你可以使用 Element Plus 提供的各种 UI 组件,例如日期选择器、下拉框、输入框等等,以便用户可以方便地编辑 Cron 表达式。 以下是一个简单的 `Cron` 组件的示例代码: ```vue <template> <div> <el-date-picker v-model="date" type="date" placeholder="选择日期"></el-date-picker> <el-input v-model="expression" placeholder="Cron 表达式"></el-input> <!-- 其他 Element Plus 组件 --> </div> </template> <script> import { ref } from 'vue'; export default { name: 'Cron', setup() { const date = ref(null); const expression = ref(''); // 其他逻辑处理 return { date, expression, // 其他返回值 }; }, }; </script> ``` 当用户对表单进行编辑后,你需要将表单数据转换为 Cron 表达式。你可以使用一个名为 `cronstrue` 的 JavaScript 库,该库可以将 Cron 表达式转换为人类可读的文本,或将人类可读的文本转换为 Cron 表达式。你可以使用以下命令将其安装: ``` npm install cronstrue ``` 在组件中,你可以编写一个计算属性,将用户编辑的表单数据转换为 Cron 表达式: ```vue <script> import { ref, computed } from 'vue'; import cronstrue from 'cronstrue'; export default { name: 'Cron', setup() { const date = ref(null); const expression = ref(''); const cron = computed(() => { if (!date.value || !expression.value) { return ''; } const [year, month, day] = date.value.split('-').map(Number); // 将表单数据转换为 Cron 表达式 const cronExpression = `0 0 0 ${day} ${month} ? ${year}`; // 将 Cron 表达式转换为人类可读的文本 return cronstrue.toString(cronExpression); }); // 其他逻辑处理 return { date, expression, cron, // 其他返回值 }; }, }; </script> ``` 最后,你需要将 `Cron` 组件导出,以便在其他组件中使用。例如,在一个名为 `App` 的 Vue 组件中,你可以使用以下方式使用 `Cron` 组件: ```vue <template> <div> <Cron /> </div> </template> <script> import Cron from './Cron.vue'; export default { name: 'App', components: { Cron, }, }; </script> ``` 希望这些指导和建议能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值