feat: 自定义预览图/文件名
This commit is contained in:
parent
755a30583f
commit
23ff03d40c
@ -68,7 +68,7 @@ const {
|
|||||||
handleRemove,
|
handleRemove,
|
||||||
beforeUpload,
|
beforeUpload,
|
||||||
innerFileList,
|
innerFileList,
|
||||||
} = useUpload(props, emit, ossIdList);
|
} = useUpload(props, emit, ossIdList, 'file');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
@ -8,7 +8,12 @@ import type {
|
|||||||
|
|
||||||
import type { ModelRef } from 'vue';
|
import type { ModelRef } from 'vue';
|
||||||
|
|
||||||
import type { BaseUploadProps, UploadEmits } from './props';
|
import type {
|
||||||
|
BaseUploadProps,
|
||||||
|
CustomGetter,
|
||||||
|
UploadEmits,
|
||||||
|
UploadType,
|
||||||
|
} from './props';
|
||||||
|
|
||||||
import type { AxiosProgressEvent, UploadResult } from '#/api';
|
import type { AxiosProgressEvent, UploadResult } from '#/api';
|
||||||
import type { OssFile } from '#/api/system/oss/model';
|
import type { OssFile } from '#/api/system/oss/model';
|
||||||
@ -83,12 +88,14 @@ export function useImagePreview() {
|
|||||||
* @param props 组件props
|
* @param props 组件props
|
||||||
* @param emit 事件
|
* @param emit 事件
|
||||||
* @param bindValue 双向绑定的idList
|
* @param bindValue 双向绑定的idList
|
||||||
|
* @param uploadType 区分是文件还是图片上传
|
||||||
* @returns hook
|
* @returns hook
|
||||||
*/
|
*/
|
||||||
export function useUpload(
|
export function useUpload(
|
||||||
props: Readonly<BaseUploadProps>,
|
props: Readonly<BaseUploadProps>,
|
||||||
emit: UploadEmits,
|
emit: UploadEmits,
|
||||||
bindValue: ModelRef<string | string[]>,
|
bindValue: ModelRef<string | string[]>,
|
||||||
|
uploadType: UploadType,
|
||||||
) {
|
) {
|
||||||
// 组件内部维护fileList
|
// 组件内部维护fileList
|
||||||
const innerFileList = ref<UploadFile[]>([]);
|
const innerFileList = ref<UploadFile[]>([]);
|
||||||
@ -114,6 +121,45 @@ export function useUpload(
|
|||||||
.join(', ');
|
.join(', ');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义文件显示名称 需要区分不同的接口
|
||||||
|
* @param cb callback
|
||||||
|
* @returns 文件名
|
||||||
|
*/
|
||||||
|
function transformFilename(cb: Parameters<CustomGetter<string>>[0]) {
|
||||||
|
if (isFunction(props.customFilename)) {
|
||||||
|
return props.customFilename(cb);
|
||||||
|
}
|
||||||
|
// info接口
|
||||||
|
if (cb.type === 'info') {
|
||||||
|
return cb.response.originalName;
|
||||||
|
}
|
||||||
|
// 上传接口
|
||||||
|
return cb.response.fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义缩略图 需要区分不同的接口
|
||||||
|
* @param cb callback
|
||||||
|
* @returns 缩略图地址
|
||||||
|
*/
|
||||||
|
function transformThumbUrl(cb: Parameters<CustomGetter<undefined>>[0]) {
|
||||||
|
if (isFunction(props.customThumbUrl)) {
|
||||||
|
return props.customThumbUrl(cb);
|
||||||
|
}
|
||||||
|
// image 默认返回图片链接
|
||||||
|
if (uploadType === 'image') {
|
||||||
|
// info接口
|
||||||
|
if (cb.type === 'info') {
|
||||||
|
return cb.response.url;
|
||||||
|
}
|
||||||
|
// 上传接口
|
||||||
|
return cb.response.url;
|
||||||
|
}
|
||||||
|
// 文件默认返回空 走antd默认的预览图逻辑
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
function handleChange(info: UploadChangeParam) {
|
function handleChange(info: UploadChangeParam) {
|
||||||
/**
|
/**
|
||||||
* 移除当前文件
|
* 移除当前文件
|
||||||
@ -141,10 +187,19 @@ export function useUpload(
|
|||||||
}
|
}
|
||||||
// 获取返回结果 为customRequest的reslove参数
|
// 获取返回结果 为customRequest的reslove参数
|
||||||
// 只有success才会走到这里
|
// 只有success才会走到这里
|
||||||
const { ossId, fileName, url } = currentFile.response as UploadResult;
|
const { ossId, url } = currentFile.response as UploadResult;
|
||||||
currentFile.url = url;
|
currentFile.url = url;
|
||||||
currentFile.fileName = fileName;
|
|
||||||
currentFile.uid = ossId;
|
currentFile.uid = ossId;
|
||||||
|
|
||||||
|
const cb = {
|
||||||
|
type: 'upload',
|
||||||
|
response: currentFile.response as UploadResult,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
currentFile.fileName = transformFilename(cb);
|
||||||
|
currentFile.name = transformFilename(cb);
|
||||||
|
currentFile.thumbUrl = transformThumbUrl(cb);
|
||||||
|
|
||||||
// ossID添加 单个文件会被当做string
|
// ossID添加 单个文件会被当做string
|
||||||
if (props.maxCount === 1) {
|
if (props.maxCount === 1) {
|
||||||
bindValue.value = ossId;
|
bindValue.value = ossId;
|
||||||
@ -262,11 +317,14 @@ export function useUpload(
|
|||||||
}
|
}
|
||||||
const resp = await ossInfo(value);
|
const resp = await ossInfo(value);
|
||||||
function transformFile(info: OssFile) {
|
function transformFile(info: OssFile) {
|
||||||
|
const cb = { type: 'info', response: info } as const;
|
||||||
|
|
||||||
const fileitem: UploadFile = {
|
const fileitem: UploadFile = {
|
||||||
uid: info.ossId,
|
uid: info.ossId,
|
||||||
name: info.originalName,
|
name: transformFilename(cb),
|
||||||
fileName: info.originalName,
|
fileName: transformFilename(cb),
|
||||||
url: info.url,
|
url: info.url,
|
||||||
|
thumbUrl: transformThumbUrl(cb),
|
||||||
status: 'done',
|
status: 'done',
|
||||||
};
|
};
|
||||||
return fileitem;
|
return fileitem;
|
||||||
|
@ -59,7 +59,7 @@ const {
|
|||||||
beforeUpload,
|
beforeUpload,
|
||||||
innerFileList,
|
innerFileList,
|
||||||
customRequest,
|
customRequest,
|
||||||
} = useUpload(props, emit, ossIdList);
|
} = useUpload(props, emit, ossIdList, 'image');
|
||||||
|
|
||||||
const { previewVisible, previewImage, handleCancel, handlePreview } =
|
const { previewVisible, previewImage, handleCancel, handlePreview } =
|
||||||
useImagePreview();
|
useImagePreview();
|
||||||
|
@ -2,9 +2,22 @@ import type { UploadFile } from 'ant-design-vue';
|
|||||||
import type { RcFile } from 'ant-design-vue/es/vc-upload/interface';
|
import type { RcFile } from 'ant-design-vue/es/vc-upload/interface';
|
||||||
|
|
||||||
import type { UploadApi, UploadResult } from '#/api';
|
import type { UploadApi, UploadResult } from '#/api';
|
||||||
|
import type { OssFile } from '#/api/system/oss/model';
|
||||||
|
|
||||||
import { UploadChangeParam } from 'ant-design-vue';
|
import { UploadChangeParam } from 'ant-design-vue';
|
||||||
|
|
||||||
|
export type UploadType = 'file' | 'image';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义返回文件名/缩略图使用 泛型控制返回是否必填
|
||||||
|
* type 为不同的接口返回值 需要自行if判断
|
||||||
|
*/
|
||||||
|
export type CustomGetter<T extends string | undefined> = (
|
||||||
|
cb:
|
||||||
|
| { response: OssFile; type: 'info' }
|
||||||
|
| { response: UploadResult; type: 'upload' },
|
||||||
|
) => T extends undefined ? string | undefined : string;
|
||||||
|
|
||||||
export interface BaseUploadProps {
|
export interface BaseUploadProps {
|
||||||
/**
|
/**
|
||||||
* 上传接口
|
* 上传接口
|
||||||
@ -99,6 +112,14 @@ export interface BaseUploadProps {
|
|||||||
* @default true
|
* @default true
|
||||||
*/
|
*/
|
||||||
abortOnUnmounted?: boolean;
|
abortOnUnmounted?: boolean;
|
||||||
|
/**
|
||||||
|
* 自定义文件名 需要区分两个接口的返回值
|
||||||
|
*/
|
||||||
|
customFilename?: CustomGetter<string>;
|
||||||
|
/**
|
||||||
|
* 自定义缩略图 需要区分两个接口的返回值
|
||||||
|
*/
|
||||||
|
customThumbUrl?: CustomGetter<undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UploadEmits {
|
export interface UploadEmits {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { UploadFile } from 'ant-design-vue/es/upload/interface';
|
import type { UploadFile } from 'ant-design-vue/es/upload/interface';
|
||||||
|
|
||||||
|
import type { CustomGetter } from '#/components/upload/src/props';
|
||||||
|
|
||||||
import { h, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
@ -34,32 +36,40 @@ const showComponent = ref(true);
|
|||||||
|
|
||||||
const { imageListOptions, currentImageListType } = useImageType();
|
const { imageListOptions, currentImageListType } = useImageType();
|
||||||
const { fileListOptions, currentFileListType } = useFileType();
|
const { fileListOptions, currentFileListType } = useFileType();
|
||||||
|
|
||||||
|
const customName: CustomGetter<string> = (cb) => {
|
||||||
|
if (cb.type === 'info') {
|
||||||
|
return `加上自定义前缀显示 - ${cb.response.originalName.toUpperCase()}`;
|
||||||
|
}
|
||||||
|
return `加上自定义前缀显示 - ${cb.response.fileName.toUpperCase()}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const customThumbnailUrl: CustomGetter<undefined> = () => {
|
||||||
|
return 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp';
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<Card title="单图片上传, 会绑定为string" size="small">
|
<Card title="单上传, 会绑定为string" size="small">
|
||||||
<ImageUpload v-model:value="singleImageId" />
|
<ImageUpload v-model:value="singleImageId" />
|
||||||
当前绑定值: {{ singleImageId }}
|
当前绑定值: {{ singleImageId }}
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card title="单文件上传, 会绑定为string" size="small">
|
<FileUpload class="mt-6" v-model:value="singleFileId" />
|
||||||
<FileUpload v-model:value="singleFileId" />
|
|
||||||
当前绑定值: {{ singleFileId }}
|
当前绑定值: {{ singleFileId }}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card title="多图片上传, maxCount参数控制(开启深度监听)" size="small">
|
<Card title="多上传, maxCount参数控制(开启深度监听)" size="small">
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
v-model:value="multipleImageId"
|
v-model:value="multipleImageId"
|
||||||
:max-count="3"
|
:max-count="3"
|
||||||
:deep-watch="true"
|
:deep-watch="true"
|
||||||
/>
|
/>
|
||||||
当前绑定值: {{ multipleImageId }}
|
当前绑定值: {{ multipleImageId }}
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card title="多文件上传, maxCount参数控制(开启深度监听)" size="small">
|
|
||||||
<FileUpload
|
<FileUpload
|
||||||
|
class="mt-6"
|
||||||
v-model:value="multipleFileId"
|
v-model:value="multipleFileId"
|
||||||
:max-count="3"
|
:max-count="3"
|
||||||
:deep-watch="true"
|
:deep-watch="true"
|
||||||
@ -79,7 +89,7 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
:help-message="false"
|
:help-message="false"
|
||||||
/>
|
/>
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
class="mt-3"
|
class="mt-6"
|
||||||
v-model:value="multipleImageId"
|
v-model:value="multipleImageId"
|
||||||
:max-count="3"
|
:max-count="3"
|
||||||
:preview="handlePreview"
|
:preview="handlePreview"
|
||||||
@ -87,14 +97,14 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card title="文件拖拽上传" size="small">
|
<Card title="文件/图片拖拽上传" size="small">
|
||||||
<FileUpload
|
<FileUpload
|
||||||
v-model:value="multipleFileId"
|
v-model:value="multipleFileId"
|
||||||
:max-count="3"
|
:max-count="3"
|
||||||
:enable-drag-upload="true"
|
:enable-drag-upload="true"
|
||||||
/>
|
/>
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
class="mt-3"
|
class="mt-6"
|
||||||
v-model:value="multipleImageId"
|
v-model:value="multipleImageId"
|
||||||
:enable-drag-upload="true"
|
:enable-drag-upload="true"
|
||||||
:max-count="6"
|
:max-count="6"
|
||||||
@ -104,7 +114,7 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
<Card title="禁用上传" size="small">
|
<Card title="禁用上传" size="small">
|
||||||
<ImageUpload :disabled="true" :max-count="3" :help-message="false" />
|
<ImageUpload :disabled="true" :max-count="3" :help-message="false" />
|
||||||
<FileUpload
|
<FileUpload
|
||||||
class="mt-3"
|
class="mt-6"
|
||||||
:disabled="true"
|
:disabled="true"
|
||||||
:max-count="3"
|
:max-count="3"
|
||||||
:help-message="false"
|
:help-message="false"
|
||||||
@ -119,7 +129,9 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
accept="*"
|
accept="*"
|
||||||
>
|
>
|
||||||
<template #helpMessage="slotProps">
|
<template #helpMessage="slotProps">
|
||||||
<div>自定义helpMessage: {{ JSON.stringify(slotProps) }}</div>
|
<div class="mt-2 font-semibold text-green-500">
|
||||||
|
自定义helpMessage: {{ JSON.stringify(slotProps) }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</FileUpload>
|
</FileUpload>
|
||||||
</Card>
|
</Card>
|
||||||
@ -130,6 +142,7 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
:accept-format="customAccept"
|
:accept-format="customAccept"
|
||||||
/>
|
/>
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
|
class="mt-6"
|
||||||
v-model:value="singleImageId"
|
v-model:value="singleImageId"
|
||||||
accept-format="自定义显示允许的文件类型"
|
accept-format="自定义显示允许的文件类型"
|
||||||
/>
|
/>
|
||||||
@ -171,6 +184,16 @@ const { fileListOptions, currentFileListType } = useFileType();
|
|||||||
:list-type="currentFileListType"
|
:list-type="currentFileListType"
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card title="自定义缩略图和文件名" size="small">
|
||||||
|
<FileUpload
|
||||||
|
v-model:value="multipleFileId"
|
||||||
|
:max-count="5"
|
||||||
|
list-type="picture"
|
||||||
|
:custom-filename="customName"
|
||||||
|
:custom-thumb-url="customThumbnailUrl"
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
Reference in New Issue
Block a user