ivue-material-plus
Version:
A high quality UI components Library with Vue.js
402 lines (318 loc) • 8.97 kB
text/typescript
import { CSSProperties, computed, ref } from 'vue';
import { isDef, isNumeric } from './validate';
// 文件上传类型
export type UploaderResultType = 'dataUrl' | 'text' | 'file' | 'url';
export type Interceptor = (...args: any[]) => Promise<boolean> | boolean;
export type UploaderMaxSize = number | string | ((file: File) => boolean);
export type UploaderFileListItem = {
url?: string;
file?: File;
content?: string;
status?: '' | 'uploading' | 'done' | 'failed';
message?: string;
beforeDelete?: Interceptor;
};
// 读取文件内容
export function readFileContent(file: File, resultType: UploaderResultType) {
return new Promise<string | void>((resolve) => {
// 文件类型
if (resultType === 'file') {
resolve();
return;
}
// url
if (resultType === 'url') {
const url = URL.createObjectURL(file);
resolve(url);
return;
}
const reader = new FileReader();
reader.onload = (event) => {
resolve((event.target as FileReader).result as string);
};
// base64
if (resultType === 'dataUrl') {
reader.readAsDataURL(file);
}
// 文本类型
else if (resultType === 'text') {
reader.readAsText(file);
}
});
}
// 文件是否超出大小
export function isOversize(
items: UploaderFileListItem | UploaderFileListItem[],
maxSize: UploaderMaxSize
): boolean {
return toArray(items).some((item) => {
if (item.file) {
if (isFunction(maxSize)) {
return maxSize(item.file);
}
return item.file.size > maxSize;
}
return false;
});
}
// 设置为数组
export function toArray<T>(item: T | T[]): T[] {
if (Array.isArray(item)) {
return item;
}
return [item];
}
// 是否是方法
// eslint-disable-next-line @typescript-eslint/ban-types
export function isFunction(val: unknown): val is Function {
return typeof val === 'function';
}
// 过滤文件
export function filterFiles(
items: UploaderFileListItem[],
maxSize: UploaderMaxSize
) {
const valid: UploaderFileListItem[] = [];
const invalid: UploaderFileListItem[] = [];
items.forEach((item) => {
if (isOversize(item, maxSize)) {
invalid.push(item);
} else {
valid.push(item);
}
});
return { valid, invalid };
}
// 设置随机字符串
export const getRandomStr = (len = 32) => {
const $chars =
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
const length = $chars.length;
let str = '';
for (let i = 0; i < len; i++) {
str += $chars.charAt(Math.floor(Math.random() * length));
}
return str;
};
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
export function isImageUrl(url: string): boolean {
return IMAGE_REGEXP.test(url);
}
// 是图片
export function isImageFile(item): boolean {
// some special urls cannot be recognized
// user can add `isImage` flag to mark it as an image url
if (item.isImage) {
return true;
}
// 文件类型
if (item.file && item.file.type) {
return item.file.type.indexOf('image') === 0;
}
// 有链接
if (item.url) {
return isImageUrl(item.url);
}
// base64
if (typeof item.content === 'string') {
return item.content.indexOf('data:image') === 0;
}
return false;
}
export function addUnit(value?: string | number): string | undefined {
if (!isDef(value)) {
return undefined;
}
return isNumeric(value) ? `${value}px` : String(value);
}
// 获取大小样式
export function getSizeStyle(
originSize?: string | number
): CSSProperties | undefined {
if (isDef(originSize)) {
const size = addUnit(originSize);
return {
width: size,
height: size,
};
}
}
// 事件代码
export const EVENT_CODE = {
tab: 'Tab',
enter: 'Enter',
space: 'Space',
left: 'ArrowLeft', // 37
up: 'ArrowUp', // 38
right: 'ArrowRight', // 39
down: 'ArrowDown', // 40
esc: 'Escape',
delete: 'Delete',
backspace: 'Backspace',
};
// 创建数组范围
export function createRange(length) {
return Array.from({ length }, (v, k) => k);
}
// 是否是颜色
export function isCssColor(color) {
return !!color && !!color.match(/^(#|(rgb|hsl)a?\()/);
}
// 设置文字颜色
export function setTextColor(color: string | string[]) {
let style: {
color?: string;
} = {};
// 是否是数组
if (Array.isArray(color)) {
style = {
color: `${color[0]}`,
};
} else if (isCssColor(color)) {
style = {
color: `${color}`,
};
} else if (color) {
const [colorName] = color.toString().trim().split(' ', 2);
style = {
color: `${colorName}--text`,
};
}
return style;
}
// 是否是纯数字
export function isValueNumber(value) {
return /^[0-9][0-9]*$/.test(value + '');
}
// 已经获取滚动条宽度
let cached;
// 获取滚动条宽度
export function getScrollBarSize(fresh?) {
if (!isClient) {
return 0;
}
if (fresh || cached === undefined) {
const inner = document.createElement('div');
inner.style.width = '100%';
inner.style.height = '200px';
const outer = document.createElement('div');
const outerStyle: CSSStyleDeclaration = outer.style;
outerStyle.position = 'absolute';
outerStyle.top = '0px';
outerStyle.left = '0px';
outerStyle.pointerEvents = 'none';
outerStyle.visibility = 'hidden';
outerStyle.width = '200px';
outerStyle.height = '150px';
outerStyle.overflow = 'hidden';
outer.appendChild(inner);
document.body.appendChild(outer);
const widthContained = inner.offsetWidth;
outer.style.overflow = 'scroll';
let widthScroll = inner.offsetWidth;
if (widthContained === widthScroll) {
widthScroll = outer.clientWidth;
}
document.body.removeChild(outer);
cached = widthContained - widthScroll;
}
return cached;
}
const zIndex = ref(0);
// 创建zindex
export const useZIndex = () => {
const currentZIndex = computed(() => 2000 + zIndex.value);
// 下一个数值
const nextZIndex = () => {
zIndex.value++;
return currentZIndex.value;
};
return {
currentZIndex,
nextZIndex,
};
};
// 是否是客户端
export const isClient = typeof window !== 'undefined';
// 是否是对象
export const isObject = (obj: unknown): boolean => {
return obj !== null && typeof obj === 'object';
};
// 是否是Element
export const isElement = (el: HTMLElement) => {
return typeof HTMLElement === 'object' && el instanceof HTMLElement;
};
// 下载文件
export async function downloadFile(url, name = '') {
if (!isClient) {
return Promise.reject();
}
try {
const res = await fetch(url);
const blob = await res.blob();
const split = res.url.split('/');
// 文件名称
const fileName = split[split.length - 1];
if (!blob) {
return Promise.reject();
}
const localUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.setAttribute('href', localUrl);
a.setAttribute('download', name || fileName);
a.click();
URL.revokeObjectURL(localUrl);
return Promise.resolve();
} catch (e) {
return Promise.reject(e);
}
}
// requestAnimationFrame
export function raf(fn: FrameRequestCallback): number {
return isClient ? requestAnimationFrame(fn) : -1;
}
// cancelAnimationFrame
export function cancelRaf(id: number) {
if (isClient) {
cancelAnimationFrame(id);
}
}
// double raf for animation
export function doubleRaf(fn: FrameRequestCallback): void {
raf(() => raf(fn));
}
// 是否是undefined
export const isUndefined = (val: any): val is undefined => val === undefined;
// Find components upward
export function findComponentsUpward(context, componentName) {
const parents = [];
const parent = context.$parent;
if (parent) {
// 找到当前组件名称
if (parent.$options.name === componentName) {
parents.push(parent);
}
// 拼接数组
return parents.concat(findComponentsUpward(parent, componentName));
} else {
return [];
}
}
// Find components upward
export function findComponentUpward(context, componentName, componentNames?) {
// 当前组件名称
if (typeof componentName === 'string') {
componentNames = [componentName];
} else {
componentNames = componentName;
}
let parent = context.$parent;
let name = parent.$options.name;
while (parent && (!name || componentNames.indexOf(name) < 0)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
return parent;
}