1. 推广员功能增强

This commit is contained in:
李琦
2026-06-12 15:07:14 +08:00
parent 2f37bf2909
commit 4090c2ca3a
16 changed files with 1006 additions and 287 deletions

View 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>