fix: 修复 Vben5.0 form-create 多图上传校验拒绝 png/jpeg/gif,isImage 兼容 MIME 与扩展名两种 accept 写法
parent
897220e19a
commit
e385823d46
|
|
@ -6,18 +6,36 @@ export function useImagesUpload() {
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
name: 'ImagesUpload',
|
name: 'ImagesUpload',
|
||||||
props: {
|
props: {
|
||||||
multiple: {
|
accept: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: false,
|
||||||
},
|
},
|
||||||
maxNumber: {
|
maxNumber: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 5,
|
default: 5,
|
||||||
},
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 5,
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
return () => (
|
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(),
|
makeRequiredRule(),
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '文件类型',
|
title: '文件类型',
|
||||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -40,12 +40,6 @@ export function useUploadFileRule() {
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'autoUpload',
|
|
||||||
title: '是否在选取文件后立即进行上传',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
field: 'drag',
|
field: 'drag',
|
||||||
|
|
@ -54,23 +48,23 @@ export function useUploadFileRule() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
field: 'isShowTip',
|
field: 'showDescription',
|
||||||
title: '是否显示提示',
|
title: '是否显示提示',
|
||||||
value: true,
|
value: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 0 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'limit',
|
field: 'maxNumber',
|
||||||
title: '数量限制',
|
title: '数量限制',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 1 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,9 @@ export function useUploadImageRule() {
|
||||||
props(_: any, { t }: any) {
|
props(_: any, { t }: any) {
|
||||||
return localeProps(t, `${name}.props`, [
|
return localeProps(t, `${name}.props`, [
|
||||||
makeRequiredRule(),
|
makeRequiredRule(),
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'drag',
|
|
||||||
title: '拖拽上传',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '图片类型限制',
|
title: '图片类型限制',
|
||||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -52,40 +46,16 @@ export function useUploadImageRule() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
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',
|
type: 'switch',
|
||||||
field: 'disabled',
|
field: 'disabled',
|
||||||
title: '是否显示删除按钮',
|
title: '是否禁用',
|
||||||
value: true,
|
value: false,
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'showBtnText',
|
|
||||||
title: '是否显示按钮文字',
|
|
||||||
value: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,9 @@ export function useUploadImagesRule() {
|
||||||
props(_: any, { t }: any) {
|
props(_: any, { t }: any) {
|
||||||
return localeProps(t, `${name}.props`, [
|
return localeProps(t, `${name}.props`, [
|
||||||
makeRequiredRule(),
|
makeRequiredRule(),
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'drag',
|
|
||||||
title: '拖拽上传',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '图片类型限制',
|
title: '图片类型限制',
|
||||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -48,40 +42,27 @@ export function useUploadImagesRule() {
|
||||||
],
|
],
|
||||||
props: {
|
props: {
|
||||||
mode: 'multiple',
|
mode: 'multiple',
|
||||||
maxNumber: 5,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 0 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'limit',
|
field: 'maxNumber',
|
||||||
title: '数量限制',
|
title: '数量限制',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 1 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'switch',
|
||||||
field: 'height',
|
field: 'disabled',
|
||||||
title: '组件高度',
|
title: '是否禁用',
|
||||||
value: '150px',
|
value: false,
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input',
|
|
||||||
field: 'width',
|
|
||||||
title: '组件宽度',
|
|
||||||
value: '150px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input',
|
|
||||||
field: 'borderradius',
|
|
||||||
title: '组件边框圆角',
|
|
||||||
value: '8px',
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,36 @@ export function useImagesUpload() {
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
name: 'ImagesUpload',
|
name: 'ImagesUpload',
|
||||||
props: {
|
props: {
|
||||||
multiple: {
|
accept: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: false,
|
||||||
},
|
},
|
||||||
maxNumber: {
|
maxNumber: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 5,
|
default: 5,
|
||||||
},
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 5,
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
return () => (
|
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(),
|
makeRequiredRule(),
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '文件类型',
|
title: '文件类型',
|
||||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -40,12 +40,6 @@ export function useUploadFileRule() {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'autoUpload',
|
|
||||||
title: '是否在选取文件后立即进行上传',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
field: 'drag',
|
field: 'drag',
|
||||||
|
|
@ -54,23 +48,23 @@ export function useUploadFileRule() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
field: 'isShowTip',
|
field: 'showDescription',
|
||||||
title: '是否显示提示',
|
title: '是否显示提示',
|
||||||
value: true,
|
value: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 0 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'limit',
|
field: 'maxNumber',
|
||||||
title: '数量限制',
|
title: '数量限制',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 1 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'switch',
|
type: 'switch',
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,9 @@ export function useUploadImageRule() {
|
||||||
props(_: any, { t }: any) {
|
props(_: any, { t }: any) {
|
||||||
return localeProps(t, `${name}.props`, [
|
return localeProps(t, `${name}.props`, [
|
||||||
makeRequiredRule(),
|
makeRequiredRule(),
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'drag',
|
|
||||||
title: '拖拽上传',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '图片类型限制',
|
title: '图片类型限制',
|
||||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -52,40 +46,16 @@ export function useUploadImageRule() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
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',
|
type: 'switch',
|
||||||
field: 'disabled',
|
field: 'disabled',
|
||||||
title: '是否显示删除按钮',
|
title: '是否禁用',
|
||||||
value: true,
|
value: false,
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'showBtnText',
|
|
||||||
title: '是否显示按钮文字',
|
|
||||||
value: true,
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -24,15 +24,9 @@ export function useUploadImagesRule() {
|
||||||
props(_: any, { t }: any) {
|
props(_: any, { t }: any) {
|
||||||
return localeProps(t, `${name}.props`, [
|
return localeProps(t, `${name}.props`, [
|
||||||
makeRequiredRule(),
|
makeRequiredRule(),
|
||||||
{
|
|
||||||
type: 'switch',
|
|
||||||
field: 'drag',
|
|
||||||
title: '拖拽上传',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'fileType',
|
field: 'accept',
|
||||||
title: '图片类型限制',
|
title: '图片类型限制',
|
||||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||||
options: [
|
options: [
|
||||||
|
|
@ -48,40 +42,27 @@ export function useUploadImagesRule() {
|
||||||
],
|
],
|
||||||
props: {
|
props: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
maxNumber: 5,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'fileSize',
|
field: 'maxSize',
|
||||||
title: '大小限制(MB)',
|
title: '大小限制(MB)',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 0 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'inputNumber',
|
type: 'inputNumber',
|
||||||
field: 'limit',
|
field: 'maxNumber',
|
||||||
title: '数量限制',
|
title: '数量限制',
|
||||||
value: 5,
|
value: 5,
|
||||||
props: { min: 0 },
|
props: { min: 1 },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'switch',
|
||||||
field: 'height',
|
field: 'disabled',
|
||||||
title: '组件高度',
|
title: '是否禁用',
|
||||||
value: '150px',
|
value: false,
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input',
|
|
||||||
field: 'width',
|
|
||||||
title: '组件宽度',
|
|
||||||
value: '150px',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'input',
|
|
||||||
field: 'borderradius',
|
|
||||||
title: '组件边框圆角',
|
|
||||||
value: '8px',
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,37 @@ export const defaultImageAccepts = [
|
||||||
'webp',
|
'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 filename 文件名
|
||||||
* @param accepts 支持的文件类型
|
* @param accepts 支持的文件类型,兼容 MIME(如 image/png)、.ext(如 .png)与纯后缀(如 png)
|
||||||
* @returns 是否为图片
|
* @returns 是否为图片
|
||||||
*/
|
*/
|
||||||
export function isImage(
|
export function isImage(
|
||||||
|
|
@ -118,7 +144,23 @@ export function isImage(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const ext = filename.split('.').pop()?.toLowerCase() || '';
|
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