ruoyi Vue 文件上传组件 2.0

简化了在页面的使用难度,在每次加载时监控 ids 是否变化,监测到变化就重新从后台通过ids获取数据

文件上传组件完整代码:

<template>
  <div>
    <el-upload
      class="upload-demo"
      :action="upload.url"
      :headers="upload.headers"
      :on-change="handleUploadChange"
      :on-success="handleUploadSuccess"
      :on-remove="handleUploadRemove"
      :on-preview="handleUploadPreview"
      :before-upload="beforeUpload"
      :file-list="fileList"
      :disabled="disabled" >
      <el-button size="small" type="primary">点击上传</el-button>
    </el-upload>

    <el-dialog
      :visible.sync="imgDialogVisible"
      append-to-body
      title="预览"
      width="800"
    >
      <img
        :src="dialogImageUrl"
        style="display: block; max-width: 100%; margin: 0 auto"
      />
    </el-dialog>
  </div>
</template>

<script>
import { getFileUrl, getFileByIds } from '@/api/system/file'
import { getToken } from '@/utils/auth'

export default {
  name: 'UploadCommon',
  props: {
    ids: {
      type: String,
      default: () => ""
    },
    disabled: {
      type: Boolean,
      default: () => false
    },
    finishUploadChange: {
      type: Function
    },
  },
  watch: {
    ids(val) {
      this.getFileList()
    }
  },
  data() {
    return {
      // 文件上传配置
      upload: {
        // 是否禁用上传
        isUploading: false,
        // 设置上传的请求头部
        headers: { Authorization: "Bearer " + getToken() },
        // 上传的地址
        url: process.env.VUE_APP_BASE_API + "/common/uploadGetId",
        // 上传的文件列表
        fileList: []
      },
      form: {
        layoutFileIds: null,
        layoutFileIdsArr: []
      },
      fileList: [],
      dialogImageUrl: "",
      imgDialogVisible: false
    }
  },
  methods: {
    handleUploadChange(file, fileList) {
      this.fileList = fileList;
    },
    handleUploadRemove(file, fileList, event) {
      console.log(file)
      this.form.layoutFileIdsArr.splice(this.form.layoutFileIdsArr.indexOf(file.id), 1)
      this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",")
      this.finishUploadChange(this.form.layoutFileIds)
    },
    handleUploadSuccess(response, file, fileList) {
      this.form.layoutFileIdsArr.push(response.id)
      this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",").toString()
      this.finishUploadChange(this.form.layoutFileIds);
    },
    resetFileList() {
      this.fileList = []
    },
    beforeUpload(file) {
      console.log(file)
      let isJPG = file.type === 'image/jpeg';
      let isTxt = file.type === 'text/plain';
      let isWord = ( file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        || file.type === 'application/msword' );
      let isPdf = file.type === 'application/pdf';
      // const isLt2M = file.size / 1024 / 1024 < 2;

      if (! (isJPG || isTxt || isWord || isPdf)) {
        this.$message.error('上传文件只能是 JPG、TXT、Word、PDF 格式!');
      }
      // if (!isLt2M) {
      //   this.$message.error('上传头像图片大小不能超过 2MB!');
      // }
      return isJPG || isTxt || isWord || isPdf;
    },
    handleUploadPreview(file) {
      let id = file.id ? file.id : file.response.id
      getFileUrl(id).then(response => {
        let fileType = response.file.fileType
        if (fileType === 'pdf' || fileType === 'txt') {
          window.open(response.file.url)
        } else if (fileType === 'docx' || fileType === 'doc') {
          // window.location.href = './wordPreview?id=' + id;
          window.open('/backstage/emergency/wordPreview?id=' + id)
        } else if (fileType === 'jpg') {
          this.dialogImageUrl = response.file.url
          this.imgDialogVisible = true
        }
      })
    },
    initUpload() {
      this.form.layoutFileIdsArr = []
      for (let i=0; i<this.fileList.length; i++) {
        this.fileList[i].name = this.fileList[i].fileName + "." + this.fileList[i].fileType
        this.fileList[i].size = this.fileList[i].fileSize
        this.form.layoutFileIdsArr.push(this.fileList[i].id)
      }
      this.form.layoutFileIds = this.form.layoutFileIdsArr.join(",")
    },
    getFileList() {
      this.form.layoutFileIds = this.ids
      if (this.ids !== "" && this.ids !== null) {
        getFileByIds(this.form.layoutFileIds).then(res => {
          this.fileList = res.file
          this.initUpload()
        })
      } else {
        this.fileList = []
        this.initUpload()
      }
    },
    clearData() {
      this.fileList = []
    }
  },
  created() {
    this.getFileList()
  }
}
</script>

<style scoped>

</style>

前端请求 js 代码

// 查询文件URL
export function getFileUrl(id) {
  return request({
    url: '/common/download/'  + id,
    method: 'get'
  })
}

// 通过 ids 查询文件列表
export function getFileByIds(ids) {
  return request({
    url: '/common/download/list?ids='  + ids,
    method: 'get'
  })
}

word 文档预览组件引入 mammoth.js 实现,组件完整代码:

<template>
  <div class="word-wrap">
    <div id="wordView" v-html="wordText" />
  </div>
</template>

<script>
// docx文档预览(只能转换.docx文档,转换过程中复杂样式被忽,居中、首行缩进等)
import mammoth from "mammoth";
import { getFileUrl } from '@/api/system/file'
export default {
  name: "EnterpriseWordPreview",
  data() {
    return {
      id: Number,
      wordText: "",
      wordURL: ''//文件地址
    };
  },
  created() {
    this.getWord();
    this.getWordText();
  },
  methods: {
    getWord() {
      let _this = this
      this.id = this.$route.query.id
      getFileUrl(this.id).then(response => {
        let fileType = response.file.fileType
         if (fileType === 'docx' || fileType === 'doc') {
          // window.location.href = './wordPreview?id=' + id;
          // console.log(response.file.fileName + "." + fileType)
          _this.wordURL = response.file.url
          _this.getWordText()
        } else {
           _this.wordText = "当前文档格式不正确"
         }
      })
    },
    getWordText() {
      let xhr = new XMLHttpRequest();
      xhr.open("get", this.wordURL, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = () => {
        if (xhr.status === 200) {
          mammoth.convertToHtml({ arrayBuffer: new Uint8Array(xhr.response) }).then((resultObject) => {
            this.$nextTick(() => {
              this.wordText = resultObject.value;
            });
          });
        }
      };
      xhr.send();
    }
  },
};
</script>

<style>
.word-wrap {
  padding: 15px;

}
.word-wrap img {
  width: 100%;
}
</style>

后端 Controller 代码

    @ApiOperation("通过文件ID获取文件URL")
    @ApiImplicitParam(name = "file", value = "文件名", dataType = "String")
    @GetMapping("/common/download/{id}")
    public AjaxResult getFileUrl(@PathVariable("id") Long id) {
        try {
            SysFile sysFile = sysFileService.selectSysFileById(id);

            AjaxResult ajax = AjaxResult.success();
            ajax.put("file", sysFile);
            return ajax;
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
        return AjaxResult.error("文件获取失败");
    }

    @ApiOperation("通过文件Ids获取文件列表")
    @ApiImplicitParam(name = "file", value = "文件名", dataType = "String")
    @GetMapping("/common/download/list")
    public AjaxResult getFileByIds(String ids) {
        try {
            AjaxResult ajax = AjaxResult.success();

            if (StringUtils.isEmpty(ids)) {
                return ajax;
            }
            List<SysFile> sysFiles = sysFileService.selectSysFileListByIds(ids);
            ajax.put("file", sysFiles);
            return ajax;
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
        return AjaxResult.error("文件获取失败");
    }

使用 find_in_set 方式通过 ids 查询文件列表的Mabtis代码(实体中存储的 ids 格式应该例如 6,15,78 的格式):

<select id="selectListByIds" parameterType="String" resultMap="SysFileResult">
        <include refid="selectSysFileVo"/>
        <where>
            <if test="ids != null and ids != '' ">
                find_in_set(id, #{ids})
            </if>
            <if test="ids == null || ids == '' ">
                id = -1
            </if>
        </where>
    </select>

实际项目中引入完整代码:

<upload-common
    :disabled="disabled"
    :finish-upload-change="finishUploadChange"
    :ids="uploadIds"
    ref="uploadCommon" >
</upload-common>

现在获取详情时只需要将实体类的 ids 传入组件即可,无需提前获取转为 JSON 格式的 文件 List,例如:

getInfo(id).then(response => {
    this.form = response.data;
    this.uploadIds = response.data.layoutFileIds
    this.open = true;
    this.title = "查看企业信息";
});

在回调函数中重新修改 form 中的 ids

finishUploadChange(ids) {
    this.form.layoutFileIds = ids
},

PS:使用时需要另外定义一个变量存储 ids ,否则在组件上传后的回调函数中会重新修改  form 表单的 ids,会出现组件中文件列表重新刷新的问题,极大影响体验。

另外可能会出现组件中列表无法刷新的问题,可以采取修改自定义 ids(此处为 uploadIds) 的或者调用组件中的清除数据方法,例如:

this.$refs.uploadCommon.clearData()

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值