【sgUploadList】自定义组件:基于elementUI的el-upload封装的上传列表组件,适用于上传附件时

sgUploadList源码

html 复制代码
<template>
  <div :class="$options.name">
    <ul class="files">
      <li v-for="(a, i) in files" :key="i">
        <el-link @click.stop="clickFile(a)">
          <img :src="getFlieThumbSrc(a)" />
          <span>附件{{ i + 1 }}:{{ a.name }}</span></el-link
        >
        <el-link
          class="remove-btn"
          v-if="!disabled"
          icon="el-icon-close"
          :underline="false"
          @click.stop="remove(a, i)"
        />
      </li>
    </ul>

    <el-upload
      v-if="!disabled"
      :action="'#'"
      :auto-upload="false"
      :disabled="disabled"
      :multiple="true"
      :on-change="change"
      :show-file-list="false"
    >
      <el-button slot="trigger" type="primary" icon="el-icon-upload2">上传文件</el-button>
      <el-alert
        style="margin-top: 10px"
        :closable="true"
        :close-text="``"
        :description="``"
        :effect="'light'"
        :show-icon="true"
        :title="alertMsg || `最多可上传${limit}个附件,每个附件大小不超过${maxSize}M`"
        :type="'warning'"
      />
    </el-upload>

    <el-image ref="image" style="display: none" src="" :preview-src-list="[previewSrc]" />
  </div>
</template>
<script>
export default {
  name: "sgUploadList",
  components: {},
  data() {
    return {
      suffixIconURLs: this.$global.resourceTypes.flatMap((v) => v.suffixIconURLs),
      accept: `*`,
      form: {}, //表单信息
      disabled: false, //是否只读
      alertMsg: ``,
      limit: 10,
      maxSize: 400,
      files: [],
      previewSrc: null,
    };
  },
  props: ["data"],
  watch: {
    data: {
      handler(newValue, oldValue) {
        // console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
        if (Object.keys(newValue || {}).length) {
          this.form = JSON.parse(JSON.stringify(newValue));
          this.disabled = this.form.disabled;
          this.alertMsg = this.form.alertMsg;
          this.files = this.form.files || [];
          this.form.accept && (this.accept = this.form.accept);
          this.form.limit && (this.limit = this.form.limit);
          this.form.maxSize && (this.maxSize = this.form.maxSize);
        } else {
          this.form = {
            // 默认字段名: 缺省值,
          };
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  methods: {
    change(file) {
      this.files.push(file.raw);
      if (this.files.length > this.limit) {
        this.$message(`最多只能上传${this.limit}个文件`);
        this.files = this.files.slice(0, this.limit);
      }
      this.$emit(`change`, { files: this.files });
    },
    remove(d, i) {
      this.files.splice(i, 1);
    },
    getSuffixByFileName(name) {
      return name.split(".").slice(-1)[0];
    },
    getFileTypeBySuffix(suffix) {
      return (this.$global.resourceTypes.find((v) => v.suffixs.includes(suffix)) || {})
        .type;
    },
    // 获取文件格式图片路径
    getFlieThumbSrc(d) {
      let rpnull = `~@/../static/img/fileType/other/rpnull.svg`;
      if (d) {
        typeof d === `string` && (d = JSON.parse(d));
        if (Object.keys(d || {}).length) {
          return this.suffixIconURLs.find((v) =>
            v.includes(`/${this.getSuffixByFileName(d.name)}.`)
          );
        } else return rpnull;
      } else return rpnull;
    },
    showImage(previewSrc) {
      this.previewSrc = previewSrc;
      this.$refs.image.showViewer = true; //显示大图
    },
    clickFile(d) {
      let isImage = false;
      if (d.fileURL) {
        isImage =
          this.getFileTypeBySuffix(this.getSuffixByFileName(d.name)) === `picture`;
        isImage ? this.showImage(d) : window.open(`${d.fileURL}`, "_blank");
      } else {
        isImage = d.type.includes(`image`);
        isImage
          ? this.$g.file2Base64Image(d, (d) => this.showImage(d))
          : this.$g.downloadByFileObject(d);
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.sgUploadList {
  .files {
    li {
      margin-bottom: 10px;
      line-height: normal;
      width: max-content;
      max-width: 100%;
      .remove-btn {
        transition: 0.382s;
        opacity: 0;
        pointer-events: none;
        transform: translateX(-100%);
      }
      &:hover {
        .remove-btn {
          opacity: 1;
          pointer-events: auto;
          transform: translateX(0%);
        }
      }

      >>> .el-link {
        transition: 0.2s;
        line-height: normal;
        img {
          width: 16px;
          height: 16px;
          object-position: center;
          object-fit: contain;
          transform: translateY(2px);
        }
      }
    }
  }
  .el-alert {
    line-height: normal;
  }
}
</style>

应用

html 复制代码
<sgUploadList
  :data="{
    files: convertBackendFiles(form.FILE_INFO_LIST || []),
    disabled: disabled_,
    limit: 10,
  }"
  @change="getUploadFiles"
/>


...


getUploadFiles({ files }) {
  this.files = files;
},
相关推荐
Sun_小杰杰哇1 天前
Dayjs常用操作使用
开发语言·前端·javascript·typescript·vue·reactjs·anti-design-vue
basestone1 天前
🚀 从重复 CRUD 到工程化封装:我是如何设计 useTableList 统一列表逻辑的
javascript·react.js·ant design
pas1361 天前
25-mini-vue fragment & Text
前端·javascript·vue.js
软件开发技术深度爱好者1 天前
JavaScript的p5.js库使用介绍
javascript·html
冴羽1 天前
CSS 新特性!瀑布流布局的终极解决方案
前端·javascript·css
满天星辰1 天前
Vue 响应式原理深度解析
前端·vue.js
码途潇潇1 天前
JavaScript有哪些数据类型?如何判断一个变量的数据类型?
前端·javascript
满天星辰1 天前
Vue真的是单向数据流?
前端·vue.js
我的写法有点潮1 天前
JS中对象是怎么运算的呢
前端·javascript·面试
悠哉摸鱼大王1 天前
NV12 转 RGB 完整指南
前端·javascript