1. 推广员功能增强
This commit is contained in:
156
apps/web-antd/src/components/form/components/upload-oss-file.vue
Normal file
156
apps/web-antd/src/components/form/components/upload-oss-file.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { Button, Upload } from 'ant-design-vue';
|
||||
import { Icon } from '#/components/icon';
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { uploadToOss } from '#/utils/oss-upload';
|
||||
|
||||
interface FileItem {
|
||||
uid: string;
|
||||
name: string;
|
||||
status: 'uploading' | 'done' | 'error';
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
modelValue?: string;
|
||||
maxCount?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: '',
|
||||
maxCount: 1,
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: string];
|
||||
}>();
|
||||
|
||||
const fileList = ref<FileItem[]>([]);
|
||||
|
||||
function syncFileListFromValue(url: string) {
|
||||
if (!url) {
|
||||
fileList.value = [];
|
||||
return;
|
||||
}
|
||||
fileList.value = [
|
||||
{
|
||||
uid: url,
|
||||
name: url.split('/').pop() || 'file',
|
||||
status: 'done',
|
||||
url,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
syncFileListFromValue(props.modelValue);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
const currentUrl =
|
||||
fileList.value.find((file) => file.status === 'done')?.url ?? '';
|
||||
if ((newVal ?? '') !== currentUrl) {
|
||||
syncFileListFromValue(newVal ?? '');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function updateModelValue() {
|
||||
const url =
|
||||
fileList.value.find((file) => file.status === 'done' && file.url)?.url ??
|
||||
'';
|
||||
emit('update:modelValue', url);
|
||||
}
|
||||
|
||||
function beforeUpload(file: File) {
|
||||
const maxSize = 20 * 1024 * 1024;
|
||||
if (file.size > maxSize) {
|
||||
return Upload.LIST_IGNORE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const customRequest = async (options: any) => {
|
||||
const { file, onProgress, onSuccess, onError } = options;
|
||||
|
||||
fileList.value = [
|
||||
{
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
status: 'uploading',
|
||||
url: '',
|
||||
},
|
||||
];
|
||||
|
||||
try {
|
||||
const uploadMethod = preferences.app.uploadMethod || 'direct';
|
||||
let res: { url: string };
|
||||
|
||||
if (uploadMethod === 'direct') {
|
||||
res = await uploadToOss({
|
||||
file: file as File,
|
||||
onProgress: (percent) => {
|
||||
onProgress?.({ percent });
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res = await uploadFile({
|
||||
file: file as File,
|
||||
});
|
||||
}
|
||||
|
||||
fileList.value = [
|
||||
{
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
status: 'done',
|
||||
url: res.url,
|
||||
},
|
||||
];
|
||||
updateModelValue();
|
||||
onSuccess?.(res);
|
||||
} catch (error) {
|
||||
fileList.value = [
|
||||
{
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
status: 'error',
|
||||
url: '',
|
||||
},
|
||||
];
|
||||
onError?.(error);
|
||||
}
|
||||
};
|
||||
|
||||
function handleRemove() {
|
||||
fileList.value = [];
|
||||
updateModelValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
const showUploadButton = computed(
|
||||
() => fileList.value.filter((item) => item.status !== 'error').length === 0,
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Upload
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeUpload"
|
||||
:custom-request="customRequest"
|
||||
:max-count="maxCount"
|
||||
list-type="text"
|
||||
accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,image/*,application/pdf"
|
||||
@remove="handleRemove"
|
||||
>
|
||||
<Button v-if="showUploadButton">
|
||||
上传文件
|
||||
<template #icon>
|
||||
<Icon icon="ant-design:cloud-upload-outlined" />
|
||||
</template>
|
||||
</Button>
|
||||
</Upload>
|
||||
</template>
|
||||
Reference in New Issue
Block a user