vue3 + js 最简单的文件上传 文件排序 异步上传

1、图示 可拖动排序

2、主代码块1

              <van-uploader
                multiple
                v-model="fileList"
                :after-read="afterRead"
                :preview-image="false"
                accept="audio/*"
                upload-icon="plus"
                upload-text="选择音频"
              >
                <van-button icon="plus" type="primary" size="small">
                  选择音频
                </van-button>

3、主代码块2

 <van-cell-group inset>
          <van-cell title="上传专辑列表(拖动排序)">
            <template #right-icon>
              <van-button
                plain
                size="small"
                type="primary"
                hairline
                @click="sortByName"
              >
                按名称排序
              </van-button>
              <van-button
                plain
                size="small"
                type="primary"
                hairline
                @click="sortBySize"
              >
                按大小排序
              </van-button>
            </template>
          </van-cell>
          <draggable
            :list="fileList"
            ghost-class="ghost"
            :force-fallback="true"
            :group="{ name: 'list', pull: 'clone' }"
            item-key="id"
          >
            <template #item="{ element, index }">
              <div class="item move">
                <label class="move">
                  <van-cell>
                    <template #title>
                      <span class="custom-title">
                        {{ index + sort + 1 }}
                        <van-icon name="music-o" style="padding: 2px" />
                        <span>{{ element.file.name }}</span>
                      </span>
                    </template>

                    <template #right-icon>
                      <div
                        style="
                          display: flex;
                          justify-content: center;
                          align-items: center;
                          padding: 3px;
                        "
                      >
                        <van-icon
                          v-show="element.file.showDelete"
                          name="delete"
                          color="red"
                          @click="deleteFile(element.file, index)"
                        />

                        <van-loading size="14" v-show="element.showLoading" />
                        <van-icon
                          name="success"
                          style="color: #07c160"
                          v-show="element.showSuccess"
                        />
                        <van-icon
                          name="cross"
                          style="color: red"
                          v-show="element.showError"
                        />
                      </div>
                    </template>
                  </van-cell>
                </label>
              </div>
            </template>
          </draggable>
          <van-cell>
            <template #title>
              <van-button
                type="success"
                v-show="showOk"
                size="small"
                block
                plain
                round
                link
                :to="{
                  path: 'episodes',
                  query: { albumId: albumId },
                }"
                >完成(点击查看专辑列表)</van-button
              >
              <van-button
                plain
                style="float: right"
                v-if="showUpload"
                @click="clickPromise"
                type="success"
                size="small"
                block
                round
              >
                <van-icon name="back-top" />点击上传
                <span style="color: red; font-size: 10px">
                  (共{{ fileList.length }}个文件)
                </span>
              </van-button>
            </template>
          </van-cell>
        </van-cell-group>

4、完整代码  html部分

<template>
  <div>
    <div>
      <div style="margin-top: 10px; margin-bottom: 10px">
        <van-cell-group inset>
          <van-cell>
            <template #title>
              <van-uploader
                multiple
                v-model="fileList"
                :after-read="afterRead"
                :preview-image="false"
                accept="audio/*"
                upload-icon="plus"
                upload-text="选择音频"
              >
                <van-button icon="plus" type="primary" size="small">
                  选择音频
                </van-button>
              </van-uploader>
              <!-- 自定义开始集数: -->
              
              <!-- <van-stepper v-model="sort" theme="round" button-size="22" /> -->
            </template>
            <template #right-icon> </template>
          </van-cell>
        </van-cell-group>
      </div>
      <div>
        <van-cell-group inset>
          <van-cell title="上传专辑列表(拖动排序)">
            <template #right-icon>
              <van-button
                plain
                size="small"
                type="primary"
                hairline
                @click="sortByName"
              >
                按名称排序
              </van-button>
              <van-button
                plain
                size="small"
                type="primary"
                hairline
                @click="sortBySize"
              >
                按大小排序
              </van-button>
            </template>
          </van-cell>
          <draggable
            :list="fileList"
            ghost-class="ghost"
            :force-fallback="true"
            :group="{ name: 'list', pull: 'clone' }"
            item-key="id"
          >
            <template #item="{ element, index }">
              <div class="item move">
                <label class="move">
                  <van-cell>
                    <template #title>
                      <span class="custom-title">
                        {{ index + sort + 1 }}
                        <van-icon name="music-o" style="padding: 2px" />
                        <span>{{ element.file.name }}</span>
                      </span>
                    </template>

                    <template #right-icon>
                      <div
                        style="
                          display: flex;
                          justify-content: center;
                          align-items: center;
                          padding: 3px;
                        "
                      >
                        <van-icon
                          v-show="element.file.showDelete"
                          name="delete"
                          color="red"
                          @click="deleteFile(element.file, index)"
                        />

                        <van-loading size="14" v-show="element.showLoading" />
                        <van-icon
                          name="success"
                          style="color: #07c160"
                          v-show="element.showSuccess"
                        />
                        <van-icon
                          name="cross"
                          style="color: red"
                          v-show="element.showError"
                        />
                      </div>
                    </template>
                  </van-cell>
                </label>
              </div>
            </template>
          </draggable>
          <van-cell>
            <template #title>
              <van-button
                type="success"
                v-show="showOk"
                size="small"
                block
                plain
                round
                link
                :to="{
                  path: 'episodes',
                  query: { albumId: albumId },
                }"
                >完成(点击查看专辑列表)</van-button
              >
              <van-button
                plain
                style="float: right"
                v-if="showUpload"
                @click="clickPromise"
                type="success"
                size="small"
                block
                round
              >
                <van-icon name="back-top" />点击上传
                <span style="color: red; font-size: 10px">
                  (共{{ fileList.length }}个文件)
                </span>
              </van-button>
            </template>
          </van-cell>
        </van-cell-group>
      </div>
    </div>
    <div style="margin: 20px">
      <span style="font-size: 12px; color: grey">
        *注:<br />1、上传连续音频<br />2、点击选择音频<br />3、可以拖拽排序或自行选择排序方式<br />4、点击上传音频
      </span>
    </div>
  </div>
  <van-overlay :show="showOverlay">
    <div class="wrapper" @click.stop>
      <div class="block" />
    </div>
    <van-loading
      vertical
      style="
        display: flex;
        justify-content: center;
        height: 100vh;
        width: 100wh;
      "
    >
      <template #icon>
        <van-icon name="star-o" size="30" />
      </template>
      正在上传,请稍等...
    </van-loading>
  </van-overlay>
</template>

 5、完整代码 js部分

<script setup>
import Draggable from "vuedraggable";
import { ref } from "vue";
import { uploadAlbum } from "../../api/index";
import "vant/lib/uploader/style";
import { useRoute } from "vue-router";
import router from "../../router";

components: {
  Draggable;
}

const route = useRoute();
const onClickLeft = () => history.back();
const toManageHome = () =>
  router.push({
    path: "/manage",
  });

const fileList = ref([]);
const albumId = route.query.albumId;
const albumName = route.query.albumName;
const sort = parseInt(route.query.sort);
const showOverlay = ref(false);
const showUpload = ref(false);
const showOk = ref(false);


function handleFileChange(e) {
  fileList.value = [...fileList.value, ...e.target.fileList];
  e.target.value = ""; // 清空input的值,以便可以重复选择文件
}

// 根据文件名排序
function sortByName() {
  fileList.value.sort((a, b) => a.file.name.localeCompare(b.file.name));
}
// 根据大小排序
function sortBySize() {
  fileList.value.sort((a, b) => a.file.size - b.file.size);
}
// 删除
const deleteFile = (file, index) => {
  fileList.value.splice(index, 1);
};
// 选完文件加几个按钮
const afterRead = (file) => {
  showUpload.value = true;
  // 如果是多文件,file会是数组
  const files = Array.isArray(file) ? file : [file];

  console.log("文件:", files);
  // 将文件添加到FormData
  files.forEach((item, index) => {
    item.file.showLoading = false;
    item.file.showSuccess = false;
    item.file.showError = false;
    item.file.showDelete = true;
    console.log("item.file", item.file);
    // formData.append("sorts", index + sort + 1);
  });
};

const tasks = ref([]);
// 异步任务
const clickPromise = async () => {
  console.log("进入", fileList.value);
  //tasks
  fileList.value.forEach((ele, index) => {
    tasks.value.push(
      () =>
        new Promise(async (resolve) => {
          fileList.value[index].showLoading = true;
          fileList.value[index].file.showDelete = false;
          let formDataPro = new FormData();
          formDataPro.append("file[]", ele.file);
          formDataPro.append("albumId", albumId);
          console.log("执行");

          try {
            const response = await uploadAlbum(formDataPro);

            console.log("返回值", response);
            if (response.data.code == 0) {
              showSuccessToast({message:response.data.data,className: 'particulars-detail-popup'});
              // showOverlay.value = false;

              fileList.value[index].showLoading = false;
              fileList.value[index].showSuccess = true;
            } else {
              showFailToast({message:response.data.msg,className: 'particulars-detail-popup'});
              fileList.value[index].showLoading = false;
              fileList.value[index].showError = true;
              // showOverlay.value = false;
            }
          } catch (e) {
            showFailToast({message:response.data.msg,className: 'particulars-detail-popup'});
            fileList.value[index].showLoading = false;
            fileList.value[index].showError = true;
          }

          resolve();
        })
    );
  });

  executeSequentialTasks();
};
// 异步执行
const executeSequentialTasks = async () => {
  showUpload.value = false;
  for (const task of tasks.value) {
    await task();
  }
  showOk.value = true;
};
</script>

 参考文献:vant4官方文档    axios官方文档

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3中使用TypeScript进行多文件,你可以按照以下步骤进行操作: 1. 首先,创建一个文件组件。你可以使用`custom-upload`组件,并通过`v-model`绑定一个表单项,用于存储上文件列表。在`<script>`标签中,引入需要的接口类型和API封装方法。 ```javascript <template> <custom-upload v-model="formInline.attachmentResultList" :attr="attrResult" /> </template> <script> import { ref } from 'vue'; // 引入Vue3的ref方法 import { uploadFile } from '@/api'; export default { setup() { const formInline = ref({ attachmentResultList: [] }); const attrResult = ref({ id: 'fileUploadId', name: 'attachmentName', limit: 999, readonly: true }); return { formInline, attrResult }; } }; </script> ``` 2. 在API文件中,定义多文件的方法`uploadFile`。该方法接收一个`FormData`类型的参数,用于包含上文件数据。通过调用`http.upload`方法,并指定上文件的URL路径和请求头,实现文件功能。 ```javascript // api.ts import http from '@/api'; import { UPLOAD_FILE } from '@/api/config/servicePort'; export const uploadFile = (params: FormData) => { return http.upload<Upload.ResFileList>(UPLOAD_FILE + '/file/uploadFile', params, { headers: { 'Content-Type': 'multipart/form-data' } }); }; ``` 3. 定义文件的接口类型。根据你的需求,可以根据接口返回的数据定义相应的类型。 ```javascript // interface.ts export namespace Upload { export interface ResFileList { id: string; fileName: string; fileUrl: string; uploadTime: string; operator: string; fileType: string; fileSize: number; fileOldname: string; } } ``` 通过上述步骤,你就可以在Vue3中使用TypeScript实现多文件的功能了。在你的组件中,用户可以选择多个文件进行上,并且上成功后,文件相关的信息将会被保存在`formInline.attachmentResultList`中,你可以根据业务需求进行进一步处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值