vue3实现文件上传

14 篇文章 0 订阅

我们要实现如下图所示效果

请添加图片描述

<template>
  <div class="form-tr" v-for="(item, index) in fileInfo" :key="index">
    <div class="title">{{item.fileName}}</div>
    <div class="widget-container">
      <div class="file-outer">
        <input type="file"
               :id="index"
               hidden
               :accept="accept" //accept设为只接受pdf文件
               @change="onChange($event, index)">
        <div class="file" @mouseenter="mouseEnterFile(index, i)" @mouseleave="mouseLeaveFile" v-for="(list, i) in item.fileList" :key="i">
          <input type="text" :id="index+'id'+i" v-model="list.fileName" class="file-input" disabled/> //放文件的input框设置为不可编辑状态
          <div class="hidden-div">{{list.fileName}}</div> //这个div的作用是占位 设置为不可见
          <i class="delete iconfont icon-cha14" v-if="showDelete === (index + 'id' + i) && item.permission" @click="deleteFile(index, i)"></i> //删除文件图标 通过permission来控制是否有删除权限
        </div>
      </div>
      <div class="button-group">
        <i class="iconfont icon-yuanlishi history" title="查看历史" v-if="item.fileList.length > 0"></i> //查看历史图标
        <i class="icon iconfont icon-tijiao5" @click="btnChange(index)" title="上传附件" v-if="item.permission"></i> //上传文件图标
      </div>
    </div>
  </div>
</template>
<script>
import {defineComponent, reactive, ref, onMounted} from 'vue';
import all_flow_tables from '@/api/all_flow_tables' // all_flow_tables 放接口的文件名
import notify from 'devextreme/ui/notify'; //notify来于devextreme ui 控件,信息提示
export default defineComponent({
  setup() {
    const fileInfo = reactive([])
    onMounted(() => {
      let taskId = 'cb0ce517-0bfb-11ed-90d1-f8633fe87771'
      all_flow_tables.getFileInfo(taskId).then(data => { // 从后台接口获取基本信息
        let Data = data.data
        fileInfo.push(...Data)
      })
    })
    const position = ref('top center') //设置信息提示的位置
    const showDelete = ref(-1) //删除图标的显示
    const accept = ref('application/pdf') //设置上传的文件格式为pdf
    const btnChange = (index) => { //点击上传文件图标后获取id为index的input
      let file = document.getElementById(index)
      file.click() //然后执行该input的点击事件,然后调用onChange 
    }
    const onChange = (e, index) => {
      let currentFile = e.target.value.slice(12) // 获取当前选择的文件并截取文件名
      let files = e.target.files[0] //获取当前选择上传的文件(需要传给后台)
      fileInfo[index].fileList.push({ //将获取的文件名放入fileInfo中并展示在页面中
        fileName: currentFile
      })
      let fileType = fileInfo[index].fileType
      let taskId = 'cb0ce517-0bfb-11ed-90d1-f8633fe87771'
      let formData = new FormData()
      formData.append('file', files)
      all_flow_tables.postUploadAppendix(fileType,taskId,formData).then(response=>{
        notify({ // 文件上传成功后的信息弹出提示
          width: 250,
          height: 40,
          message: response.data,
          position: position.value,
          type: 'success'
        })
      })
    }
    const mouseEnterFile = (index, i) => {  // 鼠标经过的文件 显示删除按钮
      let id = index + 'id' + i
      if(document.getElementById(id).value) {
        showDelete.value = index + 'id' + i
      }
    }
    const mouseLeaveFile = () => { //删除按钮隐藏
      showDelete.value = -1
    }
    const deleteFile = (index, i) => { // 删除文件
      let id = fileInfo[index].fileList[i].id
      let taskId = 'cb0ce517-0bfb-11ed-90d1-f8633fe87771'
      all_flow_tables.deleteAppendix(id, taskId).then(response => {
        if (response.code === 0) {
          notify({
            width: 250,
            height: 40,
            message: '删除成功',
            position: position.value,
            type: 'success',
          })
          fileInfo[index].fileList[i].fileName = ''
          showDelete.value = -1
        }
      })
    }
    return {
      fileInfo,
      position,
      accept,
      showDelete,
      btnChange,
      onChange,
      mouseEnterFile,
      mouseLeaveFile,
      deleteFile
    }
  },
  components: {
    // DxFileUploader
  },
})
</script>
<style scoped lang="scss">
  .form-tr{
    width: 100%;
    height: auto;
    min-height: 50px;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    border-bottom: 1px solid #99a0cd8c;
    .title{
      width: 149px;
      height: auto;
      min-height: 49px;
      text-align: left;
      display: flex;
      align-items: center;
      padding: 7px 10px;
      background-color: #fbfeff;
      font-size: 13px;
      position: absolute;
      top: 0;
      bottom: 0;
    }
    .opinion{
      width: calc(100% - 200px);
      height: 100px;
      .sign{
        width: 50%;
        height: 30px;
        line-height: 4;
        font-size: 18px;
        font-weight: 600;
      }
      .cont{
        width: 100%;
        height: 70px;
        .seal{
          width: 50%;
          height: 100%;
          float: left;
          display: flex;
          align-items: center;
          justify-content: space-evenly;
          img{
            width: 100px;
          }
        }
        .date{
          width: 45%;
          height: 80%;
          display: flex;
          justify-content: flex-end;
          align-items: flex-end;
          font-size: 18px;
        }
      }
    }
  }
  .form-tr:last-child{
    border: 0;
  }
  .widget-container{
    width: calc(100% - 150px);
    min-height: 55px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    margin-left: 149px;
    border-left: 1px solid #99a0cd8c;
    .file-outer{
      width: calc(100% - 100px);
      .file{
        text-align: left;
        margin: 5px 0;
        width: 100%;
        position: relative;
        display: flex;
        align-items: center;
        .file-input{
          border: 0;
          background-color: unset;
          width: 100%;
          position: absolute;
        }
        .hidden-div{
          width: auto;
          display: contents;
          visibility: hidden;
        }
        .delete{
          color: #ffb2b2;
          font-size: 13px;
          cursor: pointer;
          margin-left: 10px;
          z-index: 1;
        }
        .delete:hover{
          color: red;
          font-weight: bold;
        }
      }
    }
    .button-group{
      width: 80px;
      display: flex;
      align-items: center;
      justify-content: end;
      .history{
        color: darksalmon;
        font-size: 16px;
        cursor: pointer;
        margin-right: 10px;
      }
      .icon-tijiao5{
        color: #00a58a;
        margin-right: 5px;
        font-size: 18px;
        cursor: pointer;
      }
    }
  }
</style>
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值