feat: 软件包多文件上传
This commit is contained in:
@@ -4,7 +4,6 @@ import { message, Form, Upload } from 'ant-design-vue/lib';
|
|||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||||
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
import { NE_TYPE_LIST } from '@/constants/ne-constants';
|
||||||
import useDictStore from '@/store/modules/dict';
|
|
||||||
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
|
||||||
import {
|
import {
|
||||||
addNeSoftware,
|
addNeSoftware,
|
||||||
@@ -111,7 +110,7 @@ function fnModalOk() {
|
|||||||
content: t('common.operateOk'),
|
content: t('common.operateOk'),
|
||||||
duration: 3,
|
duration: 3,
|
||||||
});
|
});
|
||||||
emit('ok');
|
emit('ok', from);
|
||||||
fnModalCancel();
|
fnModalCancel();
|
||||||
} else {
|
} else {
|
||||||
message.error({
|
message.error({
|
||||||
|
|||||||
248
src/views/ne/neSoftware/components/UploadMoreFile.vue
Normal file
248
src/views/ne/neSoftware/components/UploadMoreFile.vue
Normal 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>
|
||||||
@@ -13,10 +13,14 @@ import { parseDateToStr } from '@/utils/date-utils';
|
|||||||
import { downloadFile } from '@/api/tool/file';
|
import { downloadFile } from '@/api/tool/file';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
// 异步加载组件
|
// 异步加载组件
|
||||||
const EditModal = defineAsyncComponent(
|
const EditModal = defineAsyncComponent(
|
||||||
() => import('./components/EditModal.vue')
|
() => import('./components/EditModal.vue')
|
||||||
);
|
);
|
||||||
|
const UploadMoreFile = defineAsyncComponent(
|
||||||
|
() => import('./components/UploadMoreFile.vue')
|
||||||
|
);
|
||||||
|
|
||||||
/**网元参数 */
|
/**网元参数 */
|
||||||
let neOtions = ref<Record<string, any>[]>([]);
|
let neOtions = ref<Record<string, any>[]>([]);
|
||||||
@@ -55,8 +59,6 @@ type TabeStateType = {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
/**紧凑型 */
|
/**紧凑型 */
|
||||||
size: SizeType;
|
size: SizeType;
|
||||||
/**斑马纹 */
|
|
||||||
striped: boolean;
|
|
||||||
/**搜索栏 */
|
/**搜索栏 */
|
||||||
seached: boolean;
|
seached: boolean;
|
||||||
/**记录数据 */
|
/**记录数据 */
|
||||||
@@ -67,7 +69,6 @@ type TabeStateType = {
|
|||||||
let tableState: TabeStateType = reactive({
|
let tableState: TabeStateType = reactive({
|
||||||
loading: false,
|
loading: false,
|
||||||
size: 'middle',
|
size: 'middle',
|
||||||
striped: false,
|
|
||||||
seached: false,
|
seached: false,
|
||||||
data: [],
|
data: [],
|
||||||
});
|
});
|
||||||
@@ -161,11 +162,6 @@ function fnTableSize({ key }: MenuInfo) {
|
|||||||
tableState.size = key as SizeType;
|
tableState.size = key as SizeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**表格斑马纹 */
|
|
||||||
function fnTableStriped(_record: unknown, index: number): any {
|
|
||||||
return tableState.striped && index % 2 === 1 ? 'table-striped' : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**查询列表, pageNum初始页数 */
|
/**查询列表, pageNum初始页数 */
|
||||||
function fnGetList(pageNum?: number) {
|
function fnGetList(pageNum?: number) {
|
||||||
if (tableState.loading) return;
|
if (tableState.loading) return;
|
||||||
@@ -199,6 +195,8 @@ type ModalStateType = {
|
|||||||
visibleByEdit: boolean;
|
visibleByEdit: boolean;
|
||||||
/**新增框或修改框ID */
|
/**新增框或修改框ID */
|
||||||
editId: string;
|
editId: string;
|
||||||
|
/**多文件上传 */
|
||||||
|
visibleByMoreFile: boolean;
|
||||||
/**确定按钮 loading */
|
/**确定按钮 loading */
|
||||||
confirmLoading: boolean;
|
confirmLoading: boolean;
|
||||||
};
|
};
|
||||||
@@ -207,6 +205,7 @@ type ModalStateType = {
|
|||||||
let modalState: ModalStateType = reactive({
|
let modalState: ModalStateType = reactive({
|
||||||
visibleByEdit: false,
|
visibleByEdit: false,
|
||||||
editId: '',
|
editId: '',
|
||||||
|
visibleByMoreFile: false,
|
||||||
confirmLoading: false,
|
confirmLoading: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -238,6 +237,7 @@ function fnModalEditOk() {
|
|||||||
function fnModalEditCancel() {
|
function fnModalEditCancel() {
|
||||||
modalState.editId = '';
|
modalState.editId = '';
|
||||||
modalState.visibleByEdit = false;
|
modalState.visibleByEdit = false;
|
||||||
|
modalState.visibleByMoreFile = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**删除软件包 */
|
/**删除软件包 */
|
||||||
@@ -393,10 +393,19 @@ onMounted(() => {
|
|||||||
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
<a-card :bordered="false" :body-style="{ padding: '0px' }">
|
||||||
<!-- 插槽-卡片左侧侧 -->
|
<!-- 插槽-卡片左侧侧 -->
|
||||||
<template #title>
|
<template #title>
|
||||||
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
<a-space :size="8" align="center">
|
||||||
<template #icon><PlusOutlined /></template>
|
<a-button type="primary" @click.prevent="fnModalVisibleByEdit()">
|
||||||
{{ t('common.addText') }}
|
<template #icon><PlusOutlined /></template>
|
||||||
</a-button>
|
{{ t('common.addText') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="primary"
|
||||||
|
@click.prevent="() => (modalState.visibleByMoreFile = !modalState.visibleByMoreFile)"
|
||||||
|
>
|
||||||
|
<template #icon><PlusOutlined /></template>
|
||||||
|
More File Upload
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 插槽-卡片右侧 -->
|
<!-- 插槽-卡片右侧 -->
|
||||||
@@ -411,15 +420,6 @@ onMounted(() => {
|
|||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tooltip>
|
|
||||||
<template #title>{{ t('common.zebra') }}</template>
|
|
||||||
<a-switch
|
|
||||||
v-model:checked="tableState.striped"
|
|
||||||
:checked-children="t('common.switch.show')"
|
|
||||||
:un-checked-children="t('common.switch.hide')"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</a-tooltip>
|
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template #title>{{ t('common.reloadText') }}</template>
|
<template #title>{{ t('common.reloadText') }}</template>
|
||||||
<a-button type="text" @click.prevent="fnGetList()">
|
<a-button type="text" @click.prevent="fnGetList()">
|
||||||
@@ -461,7 +461,6 @@ onMounted(() => {
|
|||||||
:loading="tableState.loading"
|
:loading="tableState.loading"
|
||||||
:data-source="tableState.data"
|
:data-source="tableState.data"
|
||||||
:size="tableState.size"
|
:size="tableState.size"
|
||||||
:row-class-name="fnTableStriped"
|
|
||||||
:pagination="tablePagination"
|
:pagination="tablePagination"
|
||||||
:scroll="{ y: 'calc(100vh - 480px)' }"
|
:scroll="{ y: 'calc(100vh - 480px)' }"
|
||||||
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
@resizeColumn="(w:number, col:any) => (col.width = w)"
|
||||||
@@ -529,6 +528,13 @@ onMounted(() => {
|
|||||||
@ok="fnModalEditOk"
|
@ok="fnModalEditOk"
|
||||||
@cancel="fnModalEditCancel"
|
@cancel="fnModalEditCancel"
|
||||||
></EditModal>
|
></EditModal>
|
||||||
|
|
||||||
|
<!-- 新增多文件上传框 -->
|
||||||
|
<UploadMoreFile
|
||||||
|
v-model:visible="modalState.visibleByMoreFile"
|
||||||
|
@ok="fnModalEditOk"
|
||||||
|
@cancel="fnModalEditCancel"
|
||||||
|
></UploadMoreFile>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -536,8 +542,4 @@ onMounted(() => {
|
|||||||
.table :deep(.ant-pagination) {
|
.table :deep(.ant-pagination) {
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table :deep(.table-striped) td {
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user