index.ts 6.28 KB
import { createVNode, VNode } from 'vue';
import { Form, FormItem, Modal } from '@arco-design/web-vue';
import { AnyObject } from '@/types/global';
import { RenderContent } from '@arco-design/web-vue/es/_utils/types';
import { ModalConfig } from '@arco-design/web-vue/es/modal/interface';
import { compact, get } from 'lodash';

type TargetContext = '_self' | '_parent' | '_blank' | '_top';

export const openWindow = (url: string, opts?: { target?: TargetContext; [key: string]: any }) => {
  const { target = '_blank', ...others } = opts || {};
  window.open(
    url,
    target,
    Object.entries(others)
      .reduce((preValue: string[], curValue) => {
        const [key, value] = curValue;
        return [...preValue, `${key}=${value}`];
      }, [])
      .join(',')
  );
};

export const regexUrl = new RegExp(
  '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
  'i'
);

export const createFormVNode = (props: AnyObject, children: VNode | VNode[]) =>
  createVNode(Form, { autoLabelWidth: true, ...props }, () => children);

export const createFormItemVNode = (props: AnyObject, children: VNode | VNode[]) =>
  createVNode(FormItem, props, { default: () => children });

export const createModalVNode = (content: RenderContent, props: Omit<ModalConfig, 'content'>) =>
  Modal.open({ content, closable: false, maskClosable: false, escToClose: false, ...props });

export const arrayToTree = (list: any[], parentId: unknown = 0, config = {}) => {
  const idKey = get(config, 'idKey', 'id');
  const parentKey = get(config, 'parentKey', 'parent_id');
  const childrenKey = get(config, 'childrenKey', 'children');
  const removeEmpty = get(config, 'removeEmpty', false);

  return list
    .filter((item) => item[parentKey] === parentId)
    .map((item) => {
      item[childrenKey] = arrayToTree(list, item[idKey], config);
      if (removeEmpty && item[childrenKey].length === 0) {
        delete item[childrenKey];
      }
      return item;
    });
};

export const findTreeParentIds = (nodeData: AnyObject[], parentId: any, config = {}): any[] => {
  const ids: any[] = [];
  const idKey = get(config, 'idKey', 'id');
  const parentKey = get(config, 'parentKey', 'parent_id');

  nodeData
    ?.filter((item) => item[idKey] === parentId)
    ?.forEach((item) => ids.push(item[idKey], ...findTreeParentIds(nodeData, item[parentKey])));

  return ids;
};

export const findTreeChildIds = (nodeData: AnyObject[], nodeId: any, config = {}): any[] => {
  const ids: any[] = [];
  const idKey = get(config, 'idKey', 'id');
  const parentKey = get(config, 'parentKey', 'parent_id');

  nodeData
    ?.filter((item) => item[parentKey] === nodeId)
    ?.forEach((item) => ids.push(item[idKey], ...findTreeChildIds(nodeData, item[idKey])));

  return ids;
};

export const bytesForHuman = (bytes: number, decimals = 2) => {
  const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];

  let i = 0;

  // eslint-disable-next-line no-plusplus
  for (i; bytes > 1024; i++) {
    bytes /= 1024;
  }

  return `${parseFloat(bytes.toFixed(decimals))} ${units[i]}`;
};

export const audioBufferToWav = (audioBuffer: AudioBuffer, len: number) => {
  const numOfChan = audioBuffer.numberOfChannels;
  const length = len * numOfChan * 2 + 44;
  const buffer = new ArrayBuffer(length);
  const view = new DataView(buffer);
  const channels: Float32Array[] = [];
  let i: number;
  let sample: number;
  let offset = 0;
  let pos = 0;

  // write WAVE header
  // eslint-disable-next-line no-use-before-define
  setUint32(0x46464952); // "RIFF"
  // eslint-disable-next-line no-use-before-define
  setUint32(length - 8); // file length - 8
  // eslint-disable-next-line no-use-before-define
  setUint32(0x45564157); // "WAVE"

  // eslint-disable-next-line no-use-before-define
  setUint32(0x20746d66); // "fmt " chunk
  // eslint-disable-next-line no-use-before-define
  setUint32(16); // length = 16
  // eslint-disable-next-line no-use-before-define
  setUint16(1); // PCM (uncompressed)
  // eslint-disable-next-line no-use-before-define
  setUint16(numOfChan);
  // eslint-disable-next-line no-use-before-define
  setUint32(audioBuffer.sampleRate);
  // eslint-disable-next-line no-use-before-define
  setUint32(audioBuffer.sampleRate * 2 * numOfChan); // avg. bytes/sec
  // eslint-disable-next-line no-use-before-define
  setUint16(numOfChan * 2); // block-align
  // eslint-disable-next-line no-use-before-define
  setUint16(16); // 16-bit (hardcoded in this demo)

  // eslint-disable-next-line no-use-before-define
  setUint32(0x61746164); // "data" - chunk
  // eslint-disable-next-line no-use-before-define
  setUint32(length - pos - 4); // chunk length

  // write interleaved data
  // eslint-disable-next-line no-plusplus
  for (i = 0; i < audioBuffer.numberOfChannels; i++) {
    // @ts-ignore
    channels.push(audioBuffer.getChannelData(i));
  }

  while (pos < length) {
    // eslint-disable-next-line no-plusplus
    for (i = 0; i < numOfChan; i++) {
      // interleave channels
      sample = Math.max(-1, Math.min(1, channels[i][offset])); // clamp
      // eslint-disable-next-line no-bitwise
      sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767) | 0; // scale to 16-bit signed int
      view.setInt16(pos, sample, true); // write 16-bit sample
      pos += 2;
    }
    // eslint-disable-next-line no-plusplus
    offset++; // next source sample
  }

  // create Blob
  return new Blob([buffer], { type: 'audio/wav' });

  function setUint16(data: number) {
    view.setUint16(pos, data, true);
    pos += 2;
  }

  function setUint32(data: number) {
    view.setUint32(pos, data, true);
    pos += 4;
  }
};

export const getLyricTimeArr = (lyric: string): string[] => {
  const times: string[] = [];

  lyric?.split('\n').forEach((item) => {
    item = item.replace(/(^\s*)|(\s*$)/g, '');
    times.push(item.substring(item.indexOf('[') + 1, item.indexOf(']')));
  });

  return compact(times);
};

export const promiseToBoolean = (callback: Promise<any> | undefined) => callback?.then(() => true).catch(() => false) || false;

export default null;