| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- <template>
- <u-upload :width="width" :height="height" :fileList="fileList" :accept="accept" :uploadIcon="uploadIcon"
- :uploadText="uploadText" @afterRead="afterRead" @delete="deletePic" :multiple="multiple"
- :maxCount="maxCount">
- </u-upload>
- </template>
- <script setup lang="ts">
- import upload from '@/utils/upload';
- interface FileItem {
- url: string;
- }
- interface UploadEvent {
- file: Array<{ url: string }>;
- }
- interface DeleteEvent {
- index: number;
- }
- interface Props {
- modelValue: string | string[] | Record<string, any> | null;
- maxCount: number;
- width: string;
- height: string;
- multiple: boolean;
- uploadText: string;
- uploadIcon: string;
- accept: string;
- isArr: boolean;
- keyUrl: string;
- isObject: boolean;
- }
- const props = withDefaults(defineProps<Props>(), {
- modelValue: () => [],
- maxCount: 1,
- width: '200rpx',
- height: '200rpx',
- multiple: true,
- uploadText: '点击上传',
- uploadIcon: 'plus',
- accept: 'image',
- isArr: false,
- keyUrl: '',
- isObject: false
- });
- const emit = defineEmits<{
- change: [value: any];
- 'update:modelValue': [value: any];
- }>();
- const fileList = ref<FileItem[]>([]);
- watch(() => props.modelValue, (ov) => {
- if (ov) {
- if (props.isObject) {
- fileList.value = [ov as FileItem];
- } else if (props.isArr) {
- if (props.keyUrl) {
- fileList.value = (ov as any[]).map(url => ({ url: url[props.keyUrl] }));
- } else {
- fileList.value = (ov as string[]).map(url => ({ url }));
- }
- } else {
- const list = (ov as string).split(',');
- fileList.value = list.map(item => ({
- url: item
- }));
- }
- }
- });
- const deletePic = (event: DeleteEvent) => {
- fileList.value.splice(event.index, 1);
- const urls = fileList.value.map(({ url }) => url);
- const imgs = urls.toString();
-
- if (props.isObject) {
- emit('update:modelValue', null);
- emit('change', null);
- } else if (props.isArr) {
- if (props.keyUrl) {
- emit('update:modelValue', fileList.value.map(({ url }) => ({ [props.keyUrl]: url })));
- emit('change', fileList.value.map(({ url }) => ({ [props.keyUrl]: url })));
- } else {
- emit('update:modelValue', urls);
- emit('change', urls);
- }
- } else {
- emit('update:modelValue', imgs);
- emit('change', imgs);
- }
- };
- const afterRead = async (event: UploadEvent) => {
- const files = event.file;
- console.log(files);
-
- // 先使用本地临时路径进行预览展示
- const startIndex = fileList.value.length;
- const tempItems = files.map(({ url }) => ({ url }));
- fileList.value = fileList.value.concat(tempItems);
- // 同步上传并在成功后用服务端URL替换临时预览
- const promises = files.map(({ url }) => upload({
- filePath: url,
- url: '/resource/oss/upload'
- }));
- try {
- const res = await Promise.all(promises);
- const uploaded: FileItem[] = [];
- res.forEach(({ code, data }) => {
- if (code === 200) {
- uploaded.push(data);
- } else {
- uploaded.push({ url: '' });
- }
- });
- // 替换对应位置的临时项为服务器返回的URL(成功的替换,失败的不动或清理)
- uploaded.forEach((item, i) => {
- const targetIndex = startIndex + i;
- if (item.url) {
- fileList.value[targetIndex] = item;
- } else {
- // 上传失败则移除该临时项
- fileList.value.splice(targetIndex, 1);
- }
- });
- const urls = fileList.value.slice(0); // 当前所有成功项
- const imgs = urls.map(({ url }) => url).toString();
- if (props.isObject) {
- emit('update:modelValue', urls[0]);
- emit('change', urls[0]);
- } else if (props.isArr) {
- if (props.keyUrl) {
- emit('update:modelValue', urls.map(({ url }) => ({ [props.keyUrl]: url })));
- emit('change', urls.map(({ url }) => ({ [props.keyUrl]: url })));
- } else {
- emit('update:modelValue', urls.map(({ url }) => url));
- emit('change', urls.map(({ url }) => url));
- }
- } else {
- emit('update:modelValue', imgs);
- emit('change', imgs);
- }
- } catch (error) {
- console.error('Upload failed:', error);
- // 全部上传失败则回滚新增的临时项
- fileList.value.splice(startIndex, tempItems.length);
- }
- };
- </script>
- <style></style>
|