mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-06 22:19:25 +08:00
229 lines
6.0 KiB
TypeScript
229 lines
6.0 KiB
TypeScript
import { Field } from '@formily/core';
|
|
import { useField } from '@formily/react';
|
|
import { reaction } from '@formily/reactive';
|
|
import { isArr, isValid, toArr as toArray } from '@formily/shared';
|
|
import { useAPIClient } from '../../../api-client';
|
|
import { UploadChangeParam } from 'antd/lib/upload';
|
|
import { UploadFile } from 'antd/lib/upload/interface';
|
|
import { useEffect } from 'react';
|
|
import { UPLOAD_PLACEHOLDER } from './placeholder';
|
|
import type { IUploadProps, UploadProps } from './type';
|
|
|
|
export const isImage = (extName: string) => {
|
|
var reg = /\.(png|jpg|gif|jpeg|webp)$/;
|
|
return reg.test(extName);
|
|
};
|
|
|
|
export const toMap = (fileList: any) => {
|
|
if (!fileList) {
|
|
return [];
|
|
}
|
|
if (typeof fileList !== 'object') {
|
|
return [];
|
|
}
|
|
let list = fileList;
|
|
if (!Array.isArray(fileList)) {
|
|
if (Object.keys({ ...fileList }).length === 0) {
|
|
return [];
|
|
}
|
|
list = [fileList];
|
|
}
|
|
console.log({ list, fileList });
|
|
return list.map((item) => {
|
|
return [item.id || item.uid, toItem(item)];
|
|
});
|
|
};
|
|
|
|
export const toImages = (fileList) => {
|
|
if (!fileList) {
|
|
return [];
|
|
}
|
|
if (typeof fileList !== 'object') {
|
|
return [];
|
|
}
|
|
if (Object.keys(fileList).length === 0) {
|
|
return [];
|
|
}
|
|
let list = fileList;
|
|
if (!Array.isArray(fileList) && typeof fileList === 'object') {
|
|
list = [fileList];
|
|
}
|
|
return list.map((item) => {
|
|
return {
|
|
...item,
|
|
title: item.title || item.name,
|
|
imageUrl: getImageByUrl(item.url, {
|
|
exclude: ['.png', '.jpg', '.jpeg', '.gif'],
|
|
}),
|
|
};
|
|
});
|
|
};
|
|
|
|
export const toArr = (value) => {
|
|
if (!isValid(value)) {
|
|
return [];
|
|
}
|
|
if (Object.keys(value).length === 0) {
|
|
return [];
|
|
}
|
|
return toArray(value);
|
|
};
|
|
|
|
export const testOpts = (ext: RegExp, options: { exclude?: string[]; include?: string[] }) => {
|
|
if (options && isArr(options.include)) {
|
|
return options.include.some((url) => ext.test(url));
|
|
}
|
|
|
|
if (options && isArr(options.exclude)) {
|
|
return !options.exclude.some((url) => ext.test(url));
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
export const getImageByUrl = (url: string, options: any) => {
|
|
for (let i = 0; i < UPLOAD_PLACEHOLDER.length; i++) {
|
|
if (UPLOAD_PLACEHOLDER[i].ext.test(url) && testOpts(UPLOAD_PLACEHOLDER[i].ext, options)) {
|
|
return UPLOAD_PLACEHOLDER[i].icon || url;
|
|
}
|
|
}
|
|
return url;
|
|
};
|
|
|
|
export const getURL = (target: any) => {
|
|
return target?.['url'] || target?.['downloadURL'] || target?.['imgURL'];
|
|
};
|
|
export const getThumbURL = (target: any) => {
|
|
return target?.['thumbUrl'] || target?.['url'] || target?.['downloadURL'] || target?.['imgURL'];
|
|
};
|
|
|
|
export const getErrorMessage = (target: any) => {
|
|
return target?.errorMessage ||
|
|
target?.errMsg ||
|
|
target?.errorMsg ||
|
|
target?.message ||
|
|
typeof target?.error === 'string'
|
|
? target.error
|
|
: '';
|
|
};
|
|
|
|
export const getState = (target: any) => {
|
|
if (target?.success === false) return 'error';
|
|
if (target?.failed === true) return 'error';
|
|
if (target?.error) return 'error';
|
|
return target?.state || target?.status;
|
|
};
|
|
|
|
export const normalizeFileList = (fileList: UploadFile[]) => {
|
|
if (fileList && fileList.length) {
|
|
return fileList.map((file, index) => {
|
|
return {
|
|
...file,
|
|
uid: file.uid || `${index}`,
|
|
status: getState(file.response) || getState(file),
|
|
url: getURL(file) || getURL(file?.response),
|
|
thumbUrl: getImageByUrl(getThumbURL(file) || getThumbURL(file?.response), {
|
|
exclude: ['.png', '.jpg', '.jpeg', '.gif'],
|
|
}),
|
|
};
|
|
});
|
|
}
|
|
return [];
|
|
};
|
|
|
|
export const useValidator = (validator: (value: any) => string) => {
|
|
const field = useField<Field>();
|
|
useEffect(() => {
|
|
const dispose = reaction(
|
|
() => field.value,
|
|
(value) => {
|
|
const message = validator(value);
|
|
field.setFeedback({
|
|
type: 'error',
|
|
code: 'UploadError',
|
|
messages: message ? [message] : [],
|
|
});
|
|
},
|
|
);
|
|
return () => {
|
|
dispose();
|
|
};
|
|
}, []);
|
|
};
|
|
|
|
export const useUploadValidator = (serviceErrorMessage = 'Upload Service Error') => {
|
|
useValidator((value) => {
|
|
const list = toArr(value);
|
|
for (let i = 0; i < list.length; i++) {
|
|
if (list[i]?.status === 'error') {
|
|
return getErrorMessage(list[i]?.response) || getErrorMessage(list[i]) || serviceErrorMessage;
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceErrorMessage, ...props }: T) {
|
|
useUploadValidator(serviceErrorMessage);
|
|
const onChange = (param: UploadChangeParam<UploadFile>) => {
|
|
props.onChange?.(normalizeFileList([...param.fileList]));
|
|
};
|
|
|
|
const api = useAPIClient();
|
|
|
|
return {
|
|
...props,
|
|
customRequest({ action, data, file, filename, headers, onError, onProgress, onSuccess, withCredentials }) {
|
|
const formData = new FormData();
|
|
if (data) {
|
|
Object.keys(data).forEach((key) => {
|
|
formData.append(key, data[key]);
|
|
});
|
|
}
|
|
formData.append(filename, file);
|
|
api.axios
|
|
.post(action, formData, {
|
|
withCredentials,
|
|
headers,
|
|
onUploadProgress: ({ total, loaded }) => {
|
|
onProgress({ percent: Math.round((loaded / total) * 100).toFixed(2) }, file);
|
|
},
|
|
})
|
|
.then(({ data }) => {
|
|
onSuccess(data, file);
|
|
})
|
|
.catch(onError);
|
|
|
|
return {
|
|
abort() {
|
|
console.log('upload progress is aborted.');
|
|
},
|
|
};
|
|
},
|
|
onChange,
|
|
};
|
|
}
|
|
|
|
export const toItem = (file) => {
|
|
if (file?.response?.data) {
|
|
file = file.response.data;
|
|
}
|
|
return {
|
|
...file,
|
|
id: file.id || file.uid,
|
|
title: file.title || file.name,
|
|
imageUrl: getImageByUrl(file.url, {
|
|
exclude: ['.png', '.jpg', '.jpeg', '.gif'],
|
|
}),
|
|
};
|
|
};
|
|
|
|
export const toFileList = (fileList: any) => {
|
|
return toArr(fileList).map(toItem);
|
|
};
|
|
|
|
export const toValue = (fileList: any) => {
|
|
return toArr(fileList)
|
|
.filter((file) => !file.response || file.status === 'done')
|
|
.map((file) => file?.response?.data || file);
|
|
};
|