【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;
},
相关推荐
black^sugar1 小时前
纯前端实现更新检测
开发语言·前端·javascript
2401_857600952 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_857600952 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL2 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
小白学大数据2 小时前
如何使用Selenium处理JavaScript动态加载的内容?
大数据·javascript·爬虫·selenium·测试工具
轻口味2 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js
2402_857583492 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
java_heartLake3 小时前
Vue3之性能优化
javascript·vue.js·性能优化
Swift社区3 小时前
HarmonyOS 实践 - 设计模式在代码中的作用
javascript
少年姜太公4 小时前
从零开始详解js中的this(下)
前端·javascript·程序员