vue3+ts 上传组件

本来是用的jeecg-vue3中的上传组件,如下图:

 功能上还是蛮全的,就是上图中这个链接的代码死活找不到,查了下,是基于antv的a-upload实现的。但是antv中也没找到,上图这个只有移入删除的功能

但是我这边的需求是点击链接可以直接在网页预览,而不是下载,移入后有个删除和下载的功能按钮。

预览这个跟后端同事搞定了,通过点击文件名直接预览,但是!!!下载的按钮想加到文件名后面是死活加不上去了,真心找不到代码,无奈只能自己写一个了

先看效果图:

样式就是根据jeecg的上传组件样式模仿的,但是,我的移入比它的多了一个下载的按钮,哈哈哈哈

 

由于项目是基于jeecg开发的,所以如过有人用的话,大概只能作为参考

这个组件并没写的特别完善,只是针对我当前的项目需求进行了开发props

目前开放的属性有:

 大家可以根据自己情况进行改造

emit('success'), 是将当前操作的fileList数据返回到父页面好进行操作处理

 

引用案例:

 

上代码:

放到了components中

 wjUpload.vue:

<template>
  <div class="wjUpload">
    <input type="file" ref="fileInput" style="display: none" @change="handleFileChange" />
    <div class="tops">
      <div class="labels">
        <label class="upSpan" :class="isDisabled == true ? 'noSpan' : ''">{{ fileLabel }}:</label>
      </div>
      <button class="upBtn" :disabled="isDisabled" @click="triggerFileSelectAndUpload">
        <Icon icon="ant-design:upload-outlined" />
        <span class="upBtnText">上传</span>
      </button>
    </div>
    <div class="bottoms" v-if="fileList.length > 0">
      <div class="b_items" v-for="(item, index) in fileList" :key="index">
        <div class="b_i_item" @mouseover="currentIndex = index" @mouseout="currentIndex = -1">
          <Icon style="margin-left: 4px" icon="ant-design:link-outlined" />
          <div class="b_i_i_a" @click="ylClick(item)">
            <a>{{ setNewItem(item) }}</a>
          </div>
          <div class="downs" v-show="currentIndex == index" @click.stop="downClick(item)">
            <Icon icon="ant-design:download-outlined" />
          </div>
          <div class="deletes" v-show="currentIndex == index && isDisabled == false" @click.stop="deleteFileClick(item, index)">
            <Icon icon="ant-design:rest-outlined" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { computed, ref, unref, onMounted, watch } from 'vue';
  import { Icon } from '/@/components/Icon';
  import { setUploads, getDownFile } from './wjUp.ts';
  import { getToken } from '/@/utils/auth';
  import { getJiaMi } from '/@/api/common/api';
  import { Bus, getYLurl, getYLurl2 } from '/@/utils/bus.js';
  // 获取emit
  const emit = defineEmits(['success']);
  const fileInput = ref(null);
  // 存放数据地址列表
  const fileList = ref<Array>([]);
  // 是否显示操作按钮--根据下标进行控制
  const currentIndex = ref<number>(-1);
  // 父页面传递的参数
  const props = defineProps({
    // label展示名称
    fileLabel: { type: String, default: () => '文件上传' },
    // 下方链接列表展示
    newFileList: { type: Array, default: () => [] },
    // 控制是否可以操作
    isDisabled: { type: Boolean, default: () => false },
  });
  onMounted(() => {
    watch(
      () => props.newFileList,
      async () => {
        console.log(props.newFileList, '----------aaaaaaaaaaaa------------sssssssssss');
        if (props.newFileList) {
          const newArr = props.newFileList;
          if (typeof newArr === 'string') {
            const fileArray = newArr.split(','); // 假设你想根据逗号来分割字符串
            fileList.value = fileArray;
            console.log('--------');
          } else {
            // 处理不是字符串的情况
            console.log('props.newFileList 不是一个字符串');
          }
        } else {
          fileList.value = [];
        }
      },
      { deep: true, immediate: true }
    );
    watch(fileList, () => {
      // 每当fileList发生变化,就将数据返回到父页面中
      emit('success', fileList.value);
    });
  });

  // 处理文件选择变化
  const handleFileChange = (event) => {
    const file = event.target.files[0];
    if (file) {
      uploadFile(file);
    }
  };

  // 上传文件
  const uploadFile = async (file) => {
    console.log(file, '二进制');
    const formData = new FormData();
    formData.append('file', file);
    const res = await setUploads({ file });
    if (res.code == 200) {
      fileList.value.push(res.result);
      emit('success', fileList.value);
    }
  };
  // 对文件路径进行处理返回文件名
  const setNewItem = (item) => {
    let str = item.slice(item.lastIndexOf('/') + 1);
    return str;
  };

  // 触发文件选择并上传
  const triggerFileSelectAndUpload = () => {
    fileInput.value.click(); // 模拟点击文件选择按钮
  };
  // 监听点击文件预览
  const ylClick = async (e) => {
    console.log(e, '------------>');
    let str = e.slice(e.lastIndexOf('/') + 1);
    let token = getToken();
    let ylUrl = getYLurl();
    let ylUrl2 = getYLurl2();
    var url = ylUrl2 + 'bcCommon/getFileStreamByLocalPath?filePath=' + e + '&fullfilename=' + str + '&XSSTOKEN=' + token; //要预览文件的访问地址
    let cs_base = window.btoa(unescape(encodeURIComponent(url)));
    const newUrls = await getJiaMi({ jiaMiCode: encodeURIComponent(cs_base) });
    window.open(ylUrl + 'onlinePreview?url=' + newUrls);
  };
  // 监听点击下载按钮
  const downClick = async (e) => {
    console.log(e, '=========================');
    // const res = await getDownFile({ filePath: e });
    // console.log(res, '=->++++++++++++>');
    let str = e.slice(e.lastIndexOf('/') + 1);
    getDownFile({ filePath: e }).then((res) => {
      console.log('res-----------', res);
      let url = window.URL.createObjectURL(new Blob([res.data]));
      let link = document.createElement('a');
      link.style.display = 'none';
      link.href = url;
      link.setAttribute('download', str);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link); //下载完成移除元素
      window.URL.revokeObjectURL(url); //释放掉blob对象
    });
  };
  // 监听点击删除按钮
  const deleteFileClick = (item, index) => {
    console.log(item, index);
    fileList.value.splice(index, 1);
    console.log('===============>', fileList.value);
    emit('success', fileList.value);
  };
</script>

<style lang="less" scoped>
  .wjUpload {
    width: 360px;
    min-height: 60px;
    margin: 10px;
    .tops {
      width: 100%;
      height: 40px;
      display: flex;
      align-items: center;
      .labels {
        width: 130px;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        .upSpan {
          position: relative;
          display: inline-flex;
          align-items: center;
          max-width: 100%;
          height: 32px;
          color: rgba(0, 0, 0, 0.85);
          font-size: 13px;
          margin-left: 26px;
        }
      }
      .upBtn {
        width: 84px;
        height: 32px;
        border: 1px solid #e5e7eb;
        background-color: #fff;
        .upBtnText {
          font-size: 14px;
          color: rgba(0, 0, 0, 0.85);
          margin-left: 8px;
        }
      }
      .upBtn:hover {
        color: #40a9ff;
        border-color: #40a9ff;
        background: #fff;
        .upBtnText {
          color: #40a9ff;
        }
      }
      .upBtn[disabled],
      .upBtn[disabled]:hover,
      .upBtn[disabled]:focus,
      .upBtn[disabled]:active {
        color: rgba(0, 0, 0, 0.25);
        border-color: #d9d9d9;
        background: #f5f5f5;
        text-shadow: none;
        box-shadow: none;
        .upBtnText {
          color: rgba(0, 0, 0, 0.25);
        }
      }
    }
    .bottoms {
      width: 100%;
      min-height: 20px;
      .b_items {
        width: 100%;
        height: 30px;
        margin: 5 0 5px 0;
        display: flex;
        align-items: center;
        .b_i_item {
          width: 240px;
          height: 22px;
          margin-left: 130px;
          display: flex;
          align-items: center;
          transition: background-color 0.3s;
          position: relative;
          .b_i_i_a {
            width: 144px;
            height: 100%;
            margin: 0 8px;
            white-space: nowrap; /* 防止文本换行 */
            overflow: hidden; /* 隐藏超出div的内容 */
            text-overflow: ellipsis; /* 超出部分显示为省略号 */
            color: #1890ff;
          }
          .downs {
            width: 22px;
            height: 22px;
            position: absolute;
            right: 4px;
            display: flex;
            align-items: center;
            justify-content: center;
          }
          .deletes {
            width: 22px;
            height: 22px;
            position: absolute;
            right: 26px;
            display: flex;
            align-items: center;
            justify-content: center;
          }
        }

        .b_i_item:hover {
          background-color: #f5f5f5;
        }
      }
    }
  }
</style>

wjUp.ts:

import { defHttp } from '/@/utils/http/axios';
enum Api {
  setUpload = '/bcCommon/upload',
  getDownFile = '/bcCommon/getFileStream',
}
// 文件上传
export const setUploads = (params) => defHttp.uploadFile({ url: Api.setUpload }, params, { isReturnResponse: true });
// 文件下载
export const getDownFile = (params?) => defHttp.get({ url: Api.getDownFile, params, responseType: 'blob' });

 

posted @ 2024-03-16 10:42  大云之下  阅读(533)  评论(0编辑  收藏  举报
大云之下