feat: 软件包多文件上传

This commit is contained in:
TsMask
2024-04-16 11:41:59 +08:00
parent 8bf4a2a9ce
commit 69c32b2593
3 changed files with 277 additions and 28 deletions

View File

@@ -0,0 +1,248 @@
<script setup lang="ts">
import { reactive, onMounted, toRaw, watch } from 'vue';
import { message, Form, Upload } from 'ant-design-vue/lib';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { addNeSoftware } from '@/api/ne/neSoftware';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { uploadFileChunk } from '@/api/tool/file';
const { t } = useI18n();
const emit = defineEmits(['ok', 'cancel', 'update:visible']);
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
});
/**对话框对象信息状态类型 */
type ModalStateType = {
/**新增框或修改框是否显示 */
visibleByMoreFile: boolean;
/**标题 */
title: string;
/**表单数据 */
from: {
neType: string;
name: string;
path: string;
status: 'done' | 'uploading';
uid: string;
version: string;
description: string;
}[];
/**确定按钮 loading */
confirmLoading: boolean;
/**上传文件 */
uploadFiles: any[];
};
/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
visibleByMoreFile: false,
title: '软件包文件',
from: [],
confirmLoading: false,
uploadFiles: [],
});
/**
* 对话框弹出确认执行函数
* 进行表达规则校验
*/
function fnModalOk() {
if (modalState.confirmLoading) return;
// 处理上传文件过滤
const uploadFiles = toRaw(modalState.uploadFiles);
const from = toRaw(modalState.from);
const softwareData: any[] = [];
for (const hasFile of uploadFiles) {
for (const itemFile of from) {
if (itemFile.uid === hasFile.uid) {
softwareData.push(itemFile);
}
}
}
// 新增软件文件
modalState.confirmLoading = true;
const hide = message.loading(t('common.loading'), 0);
Promise.all(softwareData.map(s => addNeSoftware(s)))
.then(resArr => {
const rows: any[] = [];
resArr.forEach((res, i) => {
const info = softwareData[i];
if (res.code === RESULT_CODE_SUCCESS) {
rows.push(info);
} else {
message.error({
content: `${info.neType} ${res.msg}`,
duration: 3,
});
}
});
Object.assign(modalState.from, rows);
emit('ok', rows);
fnModalCancel();
})
.finally(() => {
hide();
modalState.confirmLoading = false;
});
}
/**
* 对话框弹出关闭执行函数
* 进行表达规则校验
*/
function fnModalCancel() {
modalState.visibleByMoreFile = false;
modalState.confirmLoading = false;
modalState.uploadFiles = [];
emit('cancel');
emit('update:visible', false);
}
/**表单上传前检查或转换压缩 */
function fnBeforeUploadFile(file: FileType) {
if (modalState.confirmLoading) return false;
const fileName = file.name;
const suff = fileName.substring(fileName.lastIndexOf('.'));
if (!['.deb', '.rpm'].includes(suff)) {
message.error(
t('views.configManage.softwareManage.onlyAble', {
fileText: '(.deb、.rpm)',
}),
3
);
return Upload.LIST_IGNORE;
}
// 根据给定的软件名取版本号 ims-r2.2312.x-ub22.deb
let version = '';
const matches = fileName.match(/([0-9.]+[0-9x]+)/);
if (matches) {
version = matches[0];
}
let neType = '';
const neTypeIndex = fileName.indexOf('-');
if (neTypeIndex !== -1) {
neType = fileName.substring(0, neTypeIndex).toUpperCase();
}
// 批量文件信息
const hasItem = modalState.from.find(
item =>
item.name === fileName &&
item.neType === neType &&
item.version === version
);
if (hasItem) {
message.error(`The same file already exists ${fileName}`, 3);
return Upload.LIST_IGNORE;
}
modalState.from.push({
name: fileName,
neType: neType,
version: version,
uid: file.uid,
status: 'uploading',
path: '',
description: '',
});
return true;
}
/**表单上传文件 */
function fnUploadFile(up: UploadRequestOption) {
const file = up.file as File;
const fromItem = modalState.from.find(item => item.uid === (file as any).uid);
if (!fromItem) {
return;
}
// 发送请求
fromItem.status = 'uploading';
uploadFileChunk(file, 5, 'software').then(res => {
if (res.code === RESULT_CODE_SUCCESS) {
// 改为完成状态
const uploadFile = modalState.uploadFiles.find(
item => item.uid === (file as any).uid
);
uploadFile.percent = 100;
uploadFile.status = 'done';
// 预置到表单
fromItem.status = 'done';
fromItem.path = res.data.fileName;
} else {
message.error(res.msg, 3);
}
});
}
/**监听是否显示,初始数据 */
watch(
() => props.visible,
val => {
if (val) {
modalState.title = 'Upload More Software';
modalState.visibleByMoreFile = true;
}
}
);
onMounted(() => {});
</script>
<template>
<a-modal
width="800px"
:keyboard="false"
:mask-closable="false"
:visible="modalState.visibleByMoreFile"
:title="modalState.title"
:confirm-loading="modalState.confirmLoading"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-form
name="modalStateFrom"
layout="horizontal"
:wrapper-col="{ span: 18 }"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-form-item
:label="`Upload File (Max: ${NE_TYPE_LIST.length})`"
name="file"
>
<a-upload
name="file"
v-model:file-list="modalState.uploadFiles"
accept=".rpm,.deb"
list-type="text"
:multiple="true"
:max-count="NE_TYPE_LIST.length"
:show-upload-list="false"
:before-upload="fnBeforeUploadFile"
:custom-request="fnUploadFile"
:disabled="modalState.confirmLoading"
>
<a-button type="primary">
<template #icon>
<UploadOutlined />
</template>
Upload
</a-button>
</a-upload>
</a-form-item>
<div :key="item.uid" v-for="item in modalState.from">
{{ item.neType }} - {{ item.name }} - {{ item.version }} -
{{ item.status }}
</div>
</a-form>
</a-modal>
</template>
<style lang="less" scoped></style>