将开源版本的修改打补丁应用到商业版
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
<!-- 文件上传弹窗组件 -->
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="visible"
|
||||
title="选择文件密级并上传"
|
||||
:width="600"
|
||||
:confirm-loading="uploading"
|
||||
@ok="handleUpload"
|
||||
@cancel="handleCancel"
|
||||
:destroyOnClose="true"
|
||||
>
|
||||
<a-form layout="vertical" style="padding: 0 20px">
|
||||
<a-form-item label="文件密级" required>
|
||||
<a-radio-group v-model:value="selectedSecretLevel">
|
||||
<a-radio
|
||||
v-for="option in secretLevelOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
<a-tag :color="getSecretLevelColor(option.value)">
|
||||
{{ option.label }}
|
||||
</a-tag>
|
||||
</a-radio>
|
||||
</a-radio-group>
|
||||
<!-- <div class="secret-tip">-->
|
||||
<!-- <Icon icon="ant-design:info-circle-outlined" />-->
|
||||
<!-- 文件密级将决定谁能查看此文件,请谨慎选择-->
|
||||
<!-- </div>-->
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="选择文件" required>
|
||||
<a-upload
|
||||
:before-upload="beforeUpload"
|
||||
:file-list="tempFileList"
|
||||
@remove="handleRemoveFile"
|
||||
:multiple="multiple"
|
||||
:max-count="multiple ? undefined : 1"
|
||||
>
|
||||
<a-button>
|
||||
<Icon icon="ant-design:file-add-outlined" />
|
||||
{{ multiple ? '选择文件(可多选)' : '选择文件' }}
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
|
||||
<a-alert
|
||||
v-if="selectedFiles.length > 0"
|
||||
:message="`已选择 ${selectedFiles.length} 个文件`"
|
||||
type="info"
|
||||
show-icon
|
||||
>
|
||||
<template #description>
|
||||
<div class="selected-files-summary">
|
||||
<div v-for="(f, idx) in selectedFiles" :key="f.uid" class="summary-item">
|
||||
{{ idx + 1}}. {{ f.name }}({{ formatFileSize(f.size) }})
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-alert>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { Icon } from '/src/components/Icon';
|
||||
import { useMessage } from '/src/hooks/web/useMessage';
|
||||
import { uploadMyFile } from '/src/api/common/api';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
secretLevelOptions: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
businessId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'upload-success', 'upload-error']);
|
||||
|
||||
const selectedSecretLevel = ref<number>(1);
|
||||
const selectedFiles = ref<any[]>([]);
|
||||
const tempFileList = ref<any[]>([]);
|
||||
const uploading = ref<boolean>(false);
|
||||
|
||||
function getSecretLevelColor(level: number) {
|
||||
const colors = {
|
||||
1: 'success',
|
||||
2: 'processing',
|
||||
3: 'warning',
|
||||
4: 'error'
|
||||
};
|
||||
return colors[level] || 'default';
|
||||
}
|
||||
|
||||
function formatFileSize(bytes: number): string {
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
function beforeUpload(file) {
|
||||
const isValidSize = file.size / 1024 / 1024 < 500;
|
||||
if (!isValidSize) {
|
||||
createMessage.error(`文件"${file.name}"大小超过500MB,已跳过`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!props.multiple) {
|
||||
selectedFiles.value = [file];
|
||||
tempFileList.value = [{
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
status: 'done',
|
||||
size: file.size
|
||||
}];
|
||||
} else {
|
||||
selectedFiles.value = [...selectedFiles.value, file];
|
||||
tempFileList.value = [...tempFileList.value, {
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
status: 'done',
|
||||
size: file.size
|
||||
}];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleRemoveFile(file) {
|
||||
selectedFiles.value = selectedFiles.value.filter(f => f.uid !== file.uid);
|
||||
tempFileList.value = tempFileList.value.filter(f => f.uid !== file.uid);
|
||||
}
|
||||
|
||||
async function handleUpload() {
|
||||
if (selectedFiles.value.length === 0) {
|
||||
createMessage.warning('请先选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedSecretLevel.value) {
|
||||
createMessage.warning('请选择文件密级');
|
||||
return;
|
||||
}
|
||||
|
||||
uploading.value = true;
|
||||
|
||||
try {
|
||||
const uploadPromises = selectedFiles.value.map(file => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('secretLevel', selectedSecretLevel.value.toString());
|
||||
if (props.businessId) {
|
||||
formData.append('business_id', props.businessId);
|
||||
}
|
||||
return uploadMyFile('/sys/file/upload', formData).then(res => ({
|
||||
rawFile: file,
|
||||
response: res
|
||||
}));
|
||||
});
|
||||
|
||||
const results = await Promise.allSettled(uploadPromises);
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
const successResults: any[] = [];
|
||||
|
||||
results.forEach((r) => {
|
||||
if (r.status === 'fulfilled') {
|
||||
const result = r.value?.response?.data;
|
||||
if (result && result.success) {
|
||||
successCount++;
|
||||
successResults.push({
|
||||
fileId: result.result.fileId,
|
||||
fileName: r.value.rawFile.name,
|
||||
filePath: result.result.savePath,
|
||||
fileSize: r.value.rawFile.size,
|
||||
secretLevel: selectedSecretLevel.value,
|
||||
fileUploadType: result.result.fileUploadType,
|
||||
bound: !!props.businessId
|
||||
});
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
});
|
||||
|
||||
if (successCount > 0) {
|
||||
createMessage.success(`成功上传 ${successCount} 个文件${failCount > 0 ? `,${failCount} 个失败` : ''}`);
|
||||
emit('upload-success', { success: true, results: successResults });
|
||||
handleCancel();
|
||||
} else {
|
||||
createMessage.error('所有文件上传失败');
|
||||
emit('upload-error', new Error('所有文件上传失败'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('上传失败:', error);
|
||||
createMessage.error('文件上传失败');
|
||||
emit('upload-error', error);
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
emit('update:visible', false);
|
||||
setTimeout(() => {
|
||||
selectedSecretLevel.value = 1;
|
||||
selectedFiles.value = [];
|
||||
tempFileList.value = [];
|
||||
}, 300);
|
||||
}
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (newVal && props.secretLevelOptions.length > 0) {
|
||||
selectedSecretLevel.value = props.secretLevelOptions[0].value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.secret-tip {
|
||||
margin-top: 8px;
|
||||
color: #faad14;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.selected-files-summary {
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
|
||||
.summary-item {
|
||||
padding: 2px 0;
|
||||
font-size: 12px;
|
||||
color: #595959;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user