fix: 修复 Vben5.0 form-create 多图上传校验拒绝 png/jpeg/gif,isImage 兼容 MIME 与扩展名两种 accept 写法
parent
897220e19a
commit
e385823d46
|
|
@ -6,18 +6,36 @@ export function useImagesUpload() {
|
|||
return defineComponent({
|
||||
name: 'ImagesUpload',
|
||||
props: {
|
||||
multiple: {
|
||||
accept: {
|
||||
type: Array,
|
||||
default: () => ['image/jpeg', 'image/png', 'image/gif'],
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
maxNumber: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
return () => (
|
||||
<ImageUpload maxNumber={props.maxNumber} multiple={props.multiple} />
|
||||
<ImageUpload
|
||||
accept={props.accept as string[]}
|
||||
disabled={props.disabled}
|
||||
maxNumber={props.maxNumber}
|
||||
maxSize={props.maxSize}
|
||||
multiple={props.multiple}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function useUploadFileRule() {
|
|||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '文件类型',
|
||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||
options: [
|
||||
|
|
@ -40,12 +40,6 @@ export function useUploadFileRule() {
|
|||
mode: 'multiple',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'autoUpload',
|
||||
title: '是否在选取文件后立即进行上传',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
|
|
@ -54,23 +48,23 @@ export function useUploadFileRule() {
|
|||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'isShowTip',
|
||||
field: 'showDescription',
|
||||
title: '是否显示提示',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
field: 'maxNumber',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
props: { min: 1 },
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
|
|
|
|||
|
|
@ -24,15 +24,9 @@ export function useUploadImageRule() {
|
|||
props(_: any, { t }: any) {
|
||||
return localeProps(t, `${name}.props`, [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
|
|
@ -52,40 +46,16 @@ export function useUploadImageRule() {
|
|||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px',
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否显示删除按钮',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'showBtnText',
|
||||
title: '是否显示按钮文字',
|
||||
value: true,
|
||||
title: '是否禁用',
|
||||
value: false,
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -24,15 +24,9 @@ export function useUploadImagesRule() {
|
|||
props(_: any, { t }: any) {
|
||||
return localeProps(t, `${name}.props`, [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
|
|
@ -48,40 +42,27 @@ export function useUploadImagesRule() {
|
|||
],
|
||||
props: {
|
||||
mode: 'multiple',
|
||||
maxNumber: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
field: 'maxNumber',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
props: { min: 1 },
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px',
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用',
|
||||
value: false,
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,18 +6,36 @@ export function useImagesUpload() {
|
|||
return defineComponent({
|
||||
name: 'ImagesUpload',
|
||||
props: {
|
||||
multiple: {
|
||||
accept: {
|
||||
type: Array,
|
||||
default: () => ['image/jpeg', 'image/png', 'image/gif'],
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
maxNumber: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 5,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
return () => (
|
||||
<ImageUpload maxNumber={props.maxNumber} multiple={props.multiple} />
|
||||
<ImageUpload
|
||||
accept={props.accept as string[]}
|
||||
disabled={props.disabled}
|
||||
maxNumber={props.maxNumber}
|
||||
maxSize={props.maxSize}
|
||||
multiple={props.multiple}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function useUploadFileRule() {
|
|||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '文件类型',
|
||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||
options: [
|
||||
|
|
@ -40,12 +40,6 @@ export function useUploadFileRule() {
|
|||
multiple: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'autoUpload',
|
||||
title: '是否在选取文件后立即进行上传',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
|
|
@ -54,23 +48,23 @@ export function useUploadFileRule() {
|
|||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'isShowTip',
|
||||
field: 'showDescription',
|
||||
title: '是否显示提示',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
field: 'maxNumber',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
props: { min: 1 },
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
|
|
|
|||
|
|
@ -24,15 +24,9 @@ export function useUploadImageRule() {
|
|||
props(_: any, { t }: any) {
|
||||
return localeProps(t, `${name}.props`, [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
|
|
@ -52,40 +46,16 @@ export function useUploadImageRule() {
|
|||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px',
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否显示删除按钮',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'showBtnText',
|
||||
title: '是否显示按钮文字',
|
||||
value: true,
|
||||
title: '是否禁用',
|
||||
value: false,
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -24,15 +24,9 @@ export function useUploadImagesRule() {
|
|||
props(_: any, { t }: any) {
|
||||
return localeProps(t, `${name}.props`, [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
field: 'accept',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
|
|
@ -48,40 +42,27 @@ export function useUploadImagesRule() {
|
|||
],
|
||||
props: {
|
||||
multiple: true,
|
||||
maxNumber: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
field: 'maxSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
field: 'maxNumber',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 },
|
||||
props: { min: 1 },
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px',
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用',
|
||||
value: false,
|
||||
},
|
||||
]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -103,11 +103,37 @@ export const defaultImageAccepts = [
|
|||
'webp',
|
||||
];
|
||||
|
||||
/**
|
||||
* 图片类 MIME 子类型到扩展名的别名映射;未列出的子类型按字面量与扩展名比较
|
||||
*/
|
||||
const IMAGE_MIME_SUBTYPE_ALIASES: Record<string, string[]> = {
|
||||
apng: ['apng', 'png'],
|
||||
jpeg: ['jpeg', 'jpg'],
|
||||
pjpeg: ['jpeg', 'jpg'],
|
||||
'svg+xml': ['svg'],
|
||||
tiff: ['tif', 'tiff'],
|
||||
'x-icon': ['ico'],
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断 MIME 子类型是否与文件扩展名匹配;image/* 限定为已知图片扩展名集合
|
||||
*/
|
||||
function matchMimeSubtype(subtype: string, ext: string): boolean {
|
||||
if (subtype === '*') {
|
||||
return defaultImageAccepts.includes(ext);
|
||||
}
|
||||
const aliases = IMAGE_MIME_SUBTYPE_ALIASES[subtype];
|
||||
if (aliases) {
|
||||
return aliases.includes(ext);
|
||||
}
|
||||
return subtype === ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断文件是否为图片
|
||||
*
|
||||
* @param filename 文件名
|
||||
* @param accepts 支持的文件类型
|
||||
* @param accepts 支持的文件类型,兼容 MIME(如 image/png)、.ext(如 .png)与纯后缀(如 png)
|
||||
* @returns 是否为图片
|
||||
*/
|
||||
export function isImage(
|
||||
|
|
@ -118,7 +144,23 @@ export function isImage(
|
|||
return false;
|
||||
}
|
||||
const ext = filename.split('.').pop()?.toLowerCase() || '';
|
||||
return accepts.includes(ext);
|
||||
if (!ext) {
|
||||
return false;
|
||||
}
|
||||
return accepts.some((accept) => {
|
||||
const lower = accept.toLowerCase();
|
||||
// MIME 类型,例如 image/png ;image/* 仅放行已知图片扩展
|
||||
if (lower.includes('/')) {
|
||||
const subtype = lower.split('/').pop() || '';
|
||||
return matchMimeSubtype(subtype, ext);
|
||||
}
|
||||
// 以点号开头的扩展名,例如 .png
|
||||
if (lower.startsWith('.')) {
|
||||
return lower.slice(1) === ext;
|
||||
}
|
||||
// 纯后缀
|
||||
return lower === ext;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue