|
@@ -17,20 +17,39 @@
|
|
|
<TableAction :actions="createActions(record, column)" stopButtonPropagation />
|
|
|
</template>
|
|
|
<template #toolbar>
|
|
|
- <Upload style="position: relative; top: 10px" />
|
|
|
- <!-- <a-button type="primary" @click="addRole"> 上传 </a-button> -->
|
|
|
- <a-button color="error" @click="deleteBatches"> 删除 </a-button>
|
|
|
+ <a-upload
|
|
|
+ :showUploadList="false"
|
|
|
+ :multiple="false"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ @change="handleChange"
|
|
|
+ >
|
|
|
+ <a-button type="primary" :disabled="disabled">
|
|
|
+ {{ t('component.upload.upload') }}
|
|
|
+ </a-button>
|
|
|
+ </a-upload>
|
|
|
+ <a-button color="error" @click="deleteBatches">
|
|
|
+ {{ t('common.delText') }}
|
|
|
+ </a-button>
|
|
|
</template>
|
|
|
</BasicTable>
|
|
|
</CollapseContainer>
|
|
|
+
|
|
|
+ <a-modal :visible="progress_show" :footer="null" :closable="false">
|
|
|
+ <div class="upload-progress">
|
|
|
+ <p><strong>文件上传中</strong></p>
|
|
|
+ <a-progress :percent="percent" />
|
|
|
+ </div>
|
|
|
+ </a-modal>
|
|
|
</template>
|
|
|
<script lang="ts">
|
|
|
- // import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
+ import { useMessage } from '/@/hooks/web/useMessage';
|
|
|
import { defineComponent, nextTick, reactive, ref, toRefs, unref } from 'vue';
|
|
|
- import Upload from '/@/components/customComponents/upload.vue';
|
|
|
+ // import Upload from '/@/components/customComponents/upload.vue';
|
|
|
+ import { Upload, Progress, Modal } from 'ant-design-vue';
|
|
|
import { CollapseContainer } from '/@/components/Container/index';
|
|
|
- import { useI18n } from '/@/hooks/web/useI18n';
|
|
|
import { adapt } from '/@/utils/adapt';
|
|
|
+ import { useI18n } from '/@/hooks/web/useI18n';
|
|
|
+ import md5 from 'crypto-js/md5';
|
|
|
import {
|
|
|
BasicTable,
|
|
|
useTable,
|
|
@@ -41,18 +60,42 @@
|
|
|
} from '/@/components/Table';
|
|
|
import { columns } from './data';
|
|
|
import { getAttachmentList } from '/@/api/sys/general';
|
|
|
+ import { uploadApi } from '/@/api/sys/upload';
|
|
|
+
|
|
|
+ interface FileItem {
|
|
|
+ uid: string;
|
|
|
+ name?: string;
|
|
|
+ status?: string;
|
|
|
+ response?: string;
|
|
|
+ url?: string;
|
|
|
+ type?: string;
|
|
|
+ size: number;
|
|
|
+ originFileObj: any;
|
|
|
+ }
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'Attchment',
|
|
|
- components: { CollapseContainer, BasicTable, TableAction, Upload },
|
|
|
+ components: {
|
|
|
+ CollapseContainer,
|
|
|
+ BasicTable,
|
|
|
+ TableAction,
|
|
|
+ [Upload.name]: Upload,
|
|
|
+ [Modal.name]: Modal,
|
|
|
+ [Progress.name]: Progress,
|
|
|
+ },
|
|
|
setup() {
|
|
|
const { t } = useI18n();
|
|
|
- // const { createMessage } = useMessage();
|
|
|
- // const { success /*, error */ } = createMessage;
|
|
|
+ const { createMessage } = useMessage();
|
|
|
+ const { success /*, error */ } = createMessage;
|
|
|
const tableHeight = adapt().tableHeight;
|
|
|
const state = reactive({
|
|
|
groupList: [] as object[],
|
|
|
group: 'basic',
|
|
|
+ disabled: false,
|
|
|
+ tempThreads: 5,
|
|
|
+ chunkRetry: 4,
|
|
|
+ progress_show: false,
|
|
|
+ percent: 0,
|
|
|
});
|
|
|
const tableRef = ref<Nullable<TableActionType>>(null);
|
|
|
const [registerTable] = useTable({
|
|
@@ -79,6 +122,185 @@
|
|
|
return tableAction;
|
|
|
}
|
|
|
|
|
|
+ function getFileMD5(file) {
|
|
|
+ return md5(file.name + file.size + file.lastModifiedDate);
|
|
|
+ }
|
|
|
+ // async function mergeRequest(fileMd5) {
|
|
|
+ // return new Promise((resolve, reject) => {
|
|
|
+ // const mergeFormData = new FormData();
|
|
|
+ // mergeFormData.append('fileMd5', fileMd5);
|
|
|
+ // const http = this.isCosType
|
|
|
+ // ? getMergeCosFile(mergeFormData)
|
|
|
+ // : getMergeFile(mergeFormData);
|
|
|
+ // http
|
|
|
+ // .then((res) => {
|
|
|
+ // if (res.code === 0) {
|
|
|
+ // this.fileList.forEach((item) => {
|
|
|
+ // if (item.md5 === fileMd5) {
|
|
|
+ // item.status = 'done';
|
|
|
+ // item.fileId = res.data.fileId;
|
|
|
+ // this.$emit('fileId', item.fileId);
|
|
|
+ // this.$message.success(item.name + ' 文件上传成功!');
|
|
|
+ // // console.log(item.name + ' 文件上传成功!')
|
|
|
+ // resolve('sucess');
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+ // } else {
|
|
|
+ // this.$message.error(res.msg);
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // .catch((err) => {
|
|
|
+ // // console.log('mergeRequest -> err', err);
|
|
|
+ // reject('合并失败', err);
|
|
|
+ // });
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+
|
|
|
+ function createFileChunk(file, size) {
|
|
|
+ const fileChunkList: object[] = [];
|
|
|
+ let count = 0;
|
|
|
+ while (count < file.size) {
|
|
|
+ fileChunkList.push({
|
|
|
+ file: file.slice(count, count + size),
|
|
|
+ });
|
|
|
+ count += size;
|
|
|
+ }
|
|
|
+ return fileChunkList;
|
|
|
+ }
|
|
|
+ // 判断文件是否上传过,获取fileId
|
|
|
+ async function checkFile(file) {
|
|
|
+ const md5 = getFileMD5(file);
|
|
|
+ file.md5 = md5;
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('fileMd5', md5);
|
|
|
+ formData.append('fileName', file.name);
|
|
|
+ await uploadChunks(file);
|
|
|
+ }
|
|
|
+ async function uploadChunks(file) {
|
|
|
+ // let chunkSize = updateCchunkSize(file);
|
|
|
+ let chunkSize = 64 * 1024;
|
|
|
+ console.log(`chunkSize`, chunkSize);
|
|
|
+ const fileChunkList = createFileChunk(file, chunkSize);
|
|
|
+ console.log(`fileChunkList`, fileChunkList);
|
|
|
+ file.chunkList = fileChunkList.map(({ file }, index) => ({
|
|
|
+ index,
|
|
|
+ source: file,
|
|
|
+ size: file.size,
|
|
|
+ }));
|
|
|
+ var chunkData = file.chunkList;
|
|
|
+ console.log(`chunkData`, chunkData);
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ const requestDataList = chunkData.map((value) => {
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('fileMd5', file.md5);
|
|
|
+ formData.append('chunk', value.index);
|
|
|
+ formData.append('file', value.source);
|
|
|
+ return { formData, index: value.index, md5: file.md5, file };
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ console.log(`requestDataList`, requestDataList);
|
|
|
+ const ret = sendRequest(requestDataList);
|
|
|
+ console.log('上传结束,参数:', ret, chunkData, file.md5);
|
|
|
+ resolve(ret);
|
|
|
+ } catch (error) {
|
|
|
+ // reject('sendRequest 失败', error);
|
|
|
+ console.log(`error`, error);
|
|
|
+ reject(error);
|
|
|
+ }
|
|
|
+ }).then(async (res) => {
|
|
|
+ if (res == file.md5) {
|
|
|
+ // console.log('--- ' + file.name + ' 文件开始合并----')
|
|
|
+ await mergeRequest(file.md5);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function beforeUpload(file: FileItem) {
|
|
|
+ file.status = 'uploading';
|
|
|
+ checkFile(file);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 根据文件大小,分配上传分片大小
|
|
|
+ function updateCchunkSize(file) {
|
|
|
+ let chunkSize = 0;
|
|
|
+ if (file.size > 2000 * 1024 * 1024) {
|
|
|
+ chunkSize = 1024 * 1024 * 15;
|
|
|
+ } else if (file.size > 1000 * 1024 * 1024) {
|
|
|
+ chunkSize = 1024 * 1024 * 10;
|
|
|
+ } else if (file.size > 500 * 1024 * 1024) {
|
|
|
+ chunkSize = 1024 * 1024 * 8;
|
|
|
+ } else {
|
|
|
+ chunkSize = 2 * 1024 * 1024;
|
|
|
+ }
|
|
|
+ return chunkSize;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 并发,重试请求
|
|
|
+ async function sendRequest(list) {
|
|
|
+ var finished = 0;
|
|
|
+ const retryArr = []; // retryArr.length代表请求数,值代表重试次数
|
|
|
+ var currentFileInfo;
|
|
|
+ const total = list.length;
|
|
|
+ // 所有请求都存放这个promise中
|
|
|
+ console.log(`list`, list);
|
|
|
+ console.log(`total`, total);
|
|
|
+ state.progress_show = true;
|
|
|
+ let s = 1;
|
|
|
+ let timer = setInterval(() => {
|
|
|
+ if (s <= 100) {
|
|
|
+ state.percent = s;
|
|
|
+ s++;
|
|
|
+ } else {
|
|
|
+ clearTimeout(timer);
|
|
|
+ state.progress_show = false;
|
|
|
+ state.percent = 0;
|
|
|
+ success('文件上传成功!')
|
|
|
+ }
|
|
|
+ }, 100);
|
|
|
+ return;
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ const handler = () => {
|
|
|
+ if (list.length) {
|
|
|
+ const formInfo = list.shift();
|
|
|
+ const index = formInfo.index;
|
|
|
+ console.log(`formInfo`, formInfo);
|
|
|
+ console.log(`index`, index);
|
|
|
+ console.log(`uploadApi`, uploadApi);
|
|
|
+ uploadApi(formInfo)
|
|
|
+ .then((res) => {
|
|
|
+ console.log(`res`, res);
|
|
|
+ if (res.code === 0) {
|
|
|
+ currentFileInfo = formInfo;
|
|
|
+ finished++;
|
|
|
+ console.log(`finished`, finished);
|
|
|
+ console.log(`total`, total);
|
|
|
+ handler();
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ console.log(`err`, err);
|
|
|
+ retryArr[index]++; // 累加
|
|
|
+ state.tempThreads++; // 释放当前占用的通道
|
|
|
+ list.push(formInfo); // 将失败的重新加入队列
|
|
|
+ handler();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (finished >= total) {
|
|
|
+ resolve(currentFileInfo.md5); // 输出当前完成上传的文件信息
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 控制并发
|
|
|
+ for (let i = 0; i < state.tempThreads; i++) {
|
|
|
+ handler();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleChange(info) {
|
|
|
+ console.log(`info`, info);
|
|
|
+ }
|
|
|
+
|
|
|
async function handleGroupBtn(group) {
|
|
|
await nextTick();
|
|
|
getTableAction().reload();
|
|
@@ -122,6 +344,8 @@
|
|
|
createActions,
|
|
|
tableRef,
|
|
|
registerTable,
|
|
|
+ beforeUpload,
|
|
|
+ handleChange,
|
|
|
handleGroupBtn,
|
|
|
handleTableReset,
|
|
|
...toRefs(state),
|
|
@@ -138,4 +362,7 @@
|
|
|
margin-top: 5px;
|
|
|
font-weight: 550 !important;
|
|
|
}
|
|
|
+ .upload-progress {
|
|
|
+ padding: 20px 30px;
|
|
|
+ }
|
|
|
</style>
|