|  | @@ -1,744 +1,743 @@
 | 
	
		
			
				|  |  | -import { h, unref } from 'vue';
 | 
	
		
			
				|  |  | -import type { App, Plugin } from 'vue';
 | 
	
		
			
				|  |  | -import { NIcon, NTag } from 'naive-ui';
 | 
	
		
			
				|  |  | -import { PageEnum } from '@/enums/pageEnum';
 | 
	
		
			
				|  |  | -import { isObject } from './is/index';
 | 
	
		
			
				|  |  | -import { cloneDeep } from 'lodash';
 | 
	
		
			
				|  |  | -import dayjs from 'dayjs';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -import EventEmitter from 'eventemitter3';
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const eventGlobal = new EventEmitter();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * render 图标
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function renderIcon(icon: any) {
 | 
	
		
			
				|  |  | -  return () => h(NIcon, null, { default: () => h(icon) });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * font 图标(Font class)
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function renderFontClassIcon(icon: string, iconName = 'iconfont') {
 | 
	
		
			
				|  |  | -  return () => h('span', { class: [iconName, icon] });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * font 图标(Unicode)
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function renderUnicodeIcon(icon: string, iconName = 'iconfont') {
 | 
	
		
			
				|  |  | -  return () => h('span', { class: [iconName], innerHTML: icon });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * font svg 图标
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function renderfontsvg(icon: any) {
 | 
	
		
			
				|  |  | -  return () =>
 | 
	
		
			
				|  |  | -    h(NIcon, null, {
 | 
	
		
			
				|  |  | -      default: () =>
 | 
	
		
			
				|  |  | -        h(
 | 
	
		
			
				|  |  | -          'svg',
 | 
	
		
			
				|  |  | -          { class: `icon`, 'aria-hidden': 'true' },
 | 
	
		
			
				|  |  | -          h('use', { 'xlink:href': `#${icon}` })
 | 
	
		
			
				|  |  | -        )
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * render new Tag
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
 | 
	
		
			
				|  |  | -export function renderNew(
 | 
	
		
			
				|  |  | -  type = 'warning',
 | 
	
		
			
				|  |  | -  text = 'New',
 | 
	
		
			
				|  |  | -  color: object = newTagColors
 | 
	
		
			
				|  |  | -) {
 | 
	
		
			
				|  |  | -  return () =>
 | 
	
		
			
				|  |  | -    h(
 | 
	
		
			
				|  |  | -      NTag as any,
 | 
	
		
			
				|  |  | -      {
 | 
	
		
			
				|  |  | -        type,
 | 
	
		
			
				|  |  | -        round: true,
 | 
	
		
			
				|  |  | -        size: 'small',
 | 
	
		
			
				|  |  | -        color
 | 
	
		
			
				|  |  | -      },
 | 
	
		
			
				|  |  | -      { default: () => text }
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 递归组装菜单格式
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -export function generatorMenu(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | -  return filterRouter(routerMap).map(item => {
 | 
	
		
			
				|  |  | -    const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | -    if (isRoot) {
 | 
	
		
			
				|  |  | -      console.log(item.children[0], 'isRoot');
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | -    // console.log(item)
 | 
	
		
			
				|  |  | -    const currentMenu = {
 | 
	
		
			
				|  |  | -      ...info,
 | 
	
		
			
				|  |  | -      ...info.meta,
 | 
	
		
			
				|  |  | -      label: info.meta?.title,
 | 
	
		
			
				|  |  | -      key: info.key,
 | 
	
		
			
				|  |  | -      icon: info.meta?.icon
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 是否有子菜单,并递归处理
 | 
	
		
			
				|  |  | -    if (info.children && info.children.length > 0) {
 | 
	
		
			
				|  |  | -      // Recursion
 | 
	
		
			
				|  |  | -      currentMenu.children = generatorMenu(info.children);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return currentMenu;
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 混合菜单
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function generatorMenuMix(
 | 
	
		
			
				|  |  | -  routerMap: Array<any>,
 | 
	
		
			
				|  |  | -  routerName: string,
 | 
	
		
			
				|  |  | -  location: string
 | 
	
		
			
				|  |  | -) {
 | 
	
		
			
				|  |  | -  const cloneRouterMap = cloneDeep(routerMap);
 | 
	
		
			
				|  |  | -  const newRouter = filterRouter(cloneRouterMap);
 | 
	
		
			
				|  |  | -  if (location === 'header') {
 | 
	
		
			
				|  |  | -    const firstRouter: any[] = [];
 | 
	
		
			
				|  |  | -    newRouter.forEach(item => {
 | 
	
		
			
				|  |  | -      const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | -      const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | -      info.children = undefined;
 | 
	
		
			
				|  |  | -      const currentMenu = {
 | 
	
		
			
				|  |  | -        ...info,
 | 
	
		
			
				|  |  | -        ...info.meta,
 | 
	
		
			
				|  |  | -        label: info.meta?.title,
 | 
	
		
			
				|  |  | -        key: info.name
 | 
	
		
			
				|  |  | -      };
 | 
	
		
			
				|  |  | -      firstRouter.push(currentMenu);
 | 
	
		
			
				|  |  | -    });
 | 
	
		
			
				|  |  | -    return firstRouter;
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    // 混合菜单
 | 
	
		
			
				|  |  | -    console.log('混合菜单');
 | 
	
		
			
				|  |  | -    return getChildrenRouter(
 | 
	
		
			
				|  |  | -      newRouter.filter(item => item.name === routerName)
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 递归组装子菜单
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function getChildrenRouter(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | -  return filterRouter(routerMap).map(item => {
 | 
	
		
			
				|  |  | -    const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | -    const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | -    const currentMenu = {
 | 
	
		
			
				|  |  | -      ...info,
 | 
	
		
			
				|  |  | -      ...info.meta,
 | 
	
		
			
				|  |  | -      label: info.meta?.title,
 | 
	
		
			
				|  |  | -      key: info.name
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -    // 是否有子菜单,并递归处理
 | 
	
		
			
				|  |  | -    if (info.children && info.children.length > 0) {
 | 
	
		
			
				|  |  | -      // Recursion
 | 
	
		
			
				|  |  | -      currentMenu.children = getChildrenRouter(info.children);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return currentMenu;
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 判断根路由 Router
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function isRootRouter(item: any) {
 | 
	
		
			
				|  |  | -  return item.meta?.isRoot === true;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 排除Router
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function filterRouter(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | -  return routerMap.filter(item => {
 | 
	
		
			
				|  |  | -    // console.log(
 | 
	
		
			
				|  |  | -    //   (item.meta?.hidden || false) != true &&
 | 
	
		
			
				|  |  | -    //   !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path),
 | 
	
		
			
				|  |  | -    //   '过滤完之后的路由'
 | 
	
		
			
				|  |  | -    // )
 | 
	
		
			
				|  |  | -    return (
 | 
	
		
			
				|  |  | -      (item.meta?.hidden || false) != true &&
 | 
	
		
			
				|  |  | -      !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(
 | 
	
		
			
				|  |  | -        item.path
 | 
	
		
			
				|  |  | -      )
 | 
	
		
			
				|  |  | -    );
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const withInstall = <T>(component: T, alias?: string) => {
 | 
	
		
			
				|  |  | -  const comp = component as any;
 | 
	
		
			
				|  |  | -  comp.install = (app: App) => {
 | 
	
		
			
				|  |  | -    app.component(comp.name || comp.displayName, component as any);
 | 
	
		
			
				|  |  | -    if (alias) {
 | 
	
		
			
				|  |  | -      app.config.globalProperties[alias] = component;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -  return component as T & Plugin;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - *  找到对应的节点
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -let result = null as any;
 | 
	
		
			
				|  |  | -export function getTreeItem(data: any[], key?: string | number): any {
 | 
	
		
			
				|  |  | -  data.map(item => {
 | 
	
		
			
				|  |  | -    if (item.key === key) {
 | 
	
		
			
				|  |  | -      result = item;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      if (item.children && item.children.length) {
 | 
	
		
			
				|  |  | -        getTreeItem(item.children, key);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return result;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - *  找到所有节点
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -const treeAll: any[] = [];
 | 
	
		
			
				|  |  | -export function getTreeAll(data: any[]): any[] {
 | 
	
		
			
				|  |  | -  data.map(item => {
 | 
	
		
			
				|  |  | -    treeAll.push(item.key);
 | 
	
		
			
				|  |  | -    if (item.children && item.children.length) {
 | 
	
		
			
				|  |  | -      getTreeAll(item.children);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -  return treeAll;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
 | 
	
		
			
				|  |  | -  let key: string;
 | 
	
		
			
				|  |  | -  for (key in target) {
 | 
	
		
			
				|  |  | -    src[key] = isObject(src[key])
 | 
	
		
			
				|  |  | -      ? deepMerge(src[key], target[key])
 | 
	
		
			
				|  |  | -      : (src[key] = target[key]);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return src;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Sums the passed percentage to the R, G or B of a HEX color
 | 
	
		
			
				|  |  | - * @param {string} color The color to change
 | 
	
		
			
				|  |  | - * @param {number} amount The amount to change the color by
 | 
	
		
			
				|  |  | - * @returns {string} The processed part of the color
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -function addLight(color: string, amount: number) {
 | 
	
		
			
				|  |  | -  const cc = parseInt(color, 16) + amount;
 | 
	
		
			
				|  |  | -  const c = cc > 255 ? 255 : cc;
 | 
	
		
			
				|  |  | -  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Lightens a 6 char HEX color according to the passed percentage
 | 
	
		
			
				|  |  | - * @param {string} color The color to change
 | 
	
		
			
				|  |  | - * @param {number} amount The amount to change the color by
 | 
	
		
			
				|  |  | - * @returns {string} The processed color represented as HEX
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -export function lighten(color: string, amount: number) {
 | 
	
		
			
				|  |  | -  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
 | 
	
		
			
				|  |  | -  amount = Math.trunc((255 * amount) / 100);
 | 
	
		
			
				|  |  | -  return `#${addLight(color.substring(0, 2), amount)}${addLight(
 | 
	
		
			
				|  |  | -    color.substring(2, 4),
 | 
	
		
			
				|  |  | -    amount
 | 
	
		
			
				|  |  | -  )}${addLight(color.substring(4, 6), amount)}`;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 判断是否 url
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export function isUrl(url: string) {
 | 
	
		
			
				|  |  | -  return /^(http|https):\/\//g.test(url);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** 递归清除空数据 */
 | 
	
		
			
				|  |  | -export function clearEmtryData(list: any[], key: string) {
 | 
	
		
			
				|  |  | -  for (let i = 0; i < list.length; i++) {
 | 
	
		
			
				|  |  | -    if (Array.isArray(list[i][key]) && !list[i][key].length) {
 | 
	
		
			
				|  |  | -      list[i][key] = '';
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      list[i][key] = clearEmtryData(list[i][key], key);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return list;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 秒转分
 | 
	
		
			
				|  |  | -export const getSecondRPM = (second: number, type?: string) => {
 | 
	
		
			
				|  |  | -  if (isNaN(second)) return '00:00';
 | 
	
		
			
				|  |  | -  const mm = Math.floor(second / 60)
 | 
	
		
			
				|  |  | -    .toString()
 | 
	
		
			
				|  |  | -    .padStart(2, '0');
 | 
	
		
			
				|  |  | -  const dd = Math.floor(second % 60)
 | 
	
		
			
				|  |  | -    .toString()
 | 
	
		
			
				|  |  | -    .padStart(2, '0');
 | 
	
		
			
				|  |  | -  if (type === 'cn') {
 | 
	
		
			
				|  |  | -    return mm + '分' + dd + '秒';
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    return mm + ':' + dd;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 秒转分
 | 
	
		
			
				|  |  | -export const getSecond = (second: number, type?: string) => {
 | 
	
		
			
				|  |  | -  if (isNaN(second)) return '0000';
 | 
	
		
			
				|  |  | -  const mm = Math.floor(second / 60)
 | 
	
		
			
				|  |  | -    .toString()
 | 
	
		
			
				|  |  | -    .padStart(2, '0');
 | 
	
		
			
				|  |  | -  const dd = Math.floor(second % 60)
 | 
	
		
			
				|  |  | -    .toString()
 | 
	
		
			
				|  |  | -    .padStart(2, '0');
 | 
	
		
			
				|  |  | -  return `${mm}${dd}`;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** 滚动到表单填写错误的地方 */
 | 
	
		
			
				|  |  | -export function scrollToErrorForm() {
 | 
	
		
			
				|  |  | -  const isError =
 | 
	
		
			
				|  |  | -    document.querySelector('.n-input--error-status') ||
 | 
	
		
			
				|  |  | -    document.querySelector('.n-base-selection--error-status');
 | 
	
		
			
				|  |  | -  isError?.scrollIntoView({
 | 
	
		
			
				|  |  | -    block: 'center',
 | 
	
		
			
				|  |  | -    behavior: 'smooth'
 | 
	
		
			
				|  |  | -  });
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const getTimes = (
 | 
	
		
			
				|  |  | -  times: any,
 | 
	
		
			
				|  |  | -  keys: Array<string> = [],
 | 
	
		
			
				|  |  | -  format = 'YYYY-MM-DD'
 | 
	
		
			
				|  |  | -) => {
 | 
	
		
			
				|  |  | -  if (times && times.length) {
 | 
	
		
			
				|  |  | -    return format == 'YYYY-MM-DD'
 | 
	
		
			
				|  |  | -      ? {
 | 
	
		
			
				|  |  | -          [keys[0] || 'start']: dayjs(times[0]).isValid()
 | 
	
		
			
				|  |  | -            ? dayjs(times[0]).format(format) + ' 00:00:00'
 | 
	
		
			
				|  |  | -            : '',
 | 
	
		
			
				|  |  | -          [keys[1] || 'end']: dayjs(times[1]).isValid()
 | 
	
		
			
				|  |  | -            ? dayjs(times[1]).format(format) + ' 23:59:59'
 | 
	
		
			
				|  |  | -            : ''
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      : {
 | 
	
		
			
				|  |  | -          [keys[0] || 'start']: dayjs(times[0]).isValid()
 | 
	
		
			
				|  |  | -            ? dayjs(times[0]).format(format)
 | 
	
		
			
				|  |  | -            : '',
 | 
	
		
			
				|  |  | -          [keys[1] || 'end']: dayjs(times[1]).isValid()
 | 
	
		
			
				|  |  | -            ? dayjs(times[1]).format(format)
 | 
	
		
			
				|  |  | -            : ''
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return {};
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const px2vw = (px: number): string => `${(px / 1920) * 100}vw`;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const px2vwH = (px: number): string =>
 | 
	
		
			
				|  |  | -  `${(((px / 1920) * 1920) / 1188) * 100}vw`;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const fscreen = () => {
 | 
	
		
			
				|  |  | -  const el = document.documentElement;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  //进入全屏
 | 
	
		
			
				|  |  | -  (el.requestFullscreen && el.requestFullscreen()) ||
 | 
	
		
			
				|  |  | -    (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
 | 
	
		
			
				|  |  | -    (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
 | 
	
		
			
				|  |  | -    (el.msRequestFullscreen && el.msRequestFullscreen());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  //退出全屏
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -export const exitFullscreen = () => {
 | 
	
		
			
				|  |  | -  document.exitFullscreen
 | 
	
		
			
				|  |  | -    ? document.exitFullscreen()
 | 
	
		
			
				|  |  | -    : document.mozCancelFullScreen
 | 
	
		
			
				|  |  | -    ? document.mozCancelFullScreen()
 | 
	
		
			
				|  |  | -    : document.webkitExitFullscreen
 | 
	
		
			
				|  |  | -    ? document.webkitExitFullscreen()
 | 
	
		
			
				|  |  | -    : '';
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** 检测链接格式 */
 | 
	
		
			
				|  |  | -export function checkUrlType(urlType: string) {
 | 
	
		
			
				|  |  | -  const subfix = (urlType || '').split('.').pop();
 | 
	
		
			
				|  |  | -  if (subfix === 'wav' || subfix === 'mp3' || subfix === 'm4a') {
 | 
	
		
			
				|  |  | -    return 'audio';
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return 'video';
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -const instruments: any = {
 | 
	
		
			
				|  |  | -  'Acoustic Grand Piano': '大钢琴',
 | 
	
		
			
				|  |  | -  'Bright Acoustic Piano': '明亮的钢琴',
 | 
	
		
			
				|  |  | -  'Electric Grand Piano': '电钢琴',
 | 
	
		
			
				|  |  | -  'Rhodes Piano': '柔和的电钢琴',
 | 
	
		
			
				|  |  | -  'Chorused Piano': '加合唱效果的电钢琴',
 | 
	
		
			
				|  |  | -  Harpsichord: '羽管键琴',
 | 
	
		
			
				|  |  | -  Clavichord: '科拉维科特琴',
 | 
	
		
			
				|  |  | -  Celesta: '钢片琴',
 | 
	
		
			
				|  |  | -  Glockenspiel: '钢片琴',
 | 
	
		
			
				|  |  | -  'Music box': '八音盒',
 | 
	
		
			
				|  |  | -  Vibraphone: '颤音琴',
 | 
	
		
			
				|  |  | -  Marimba: '马林巴',
 | 
	
		
			
				|  |  | -  Xylophone: '木琴',
 | 
	
		
			
				|  |  | -  'Tubular Bells': '管钟',
 | 
	
		
			
				|  |  | -  Dulcimer: '大扬琴',
 | 
	
		
			
				|  |  | -  'Hammond Organ': '击杆风琴',
 | 
	
		
			
				|  |  | -  'Percussive Organ': '打击式风琴',
 | 
	
		
			
				|  |  | -  'Rock Organ': '摇滚风琴',
 | 
	
		
			
				|  |  | -  'Church Organ': '教堂风琴',
 | 
	
		
			
				|  |  | -  'Reed Organ': '簧管风琴',
 | 
	
		
			
				|  |  | -  Accordian: '手风琴',
 | 
	
		
			
				|  |  | -  Harmonica: '口琴',
 | 
	
		
			
				|  |  | -  'Tango Accordian': '探戈手风琴',
 | 
	
		
			
				|  |  | -  'Acoustic Guitar': '钢弦吉他',
 | 
	
		
			
				|  |  | -  'Electric Guitar': '闷音电吉他',
 | 
	
		
			
				|  |  | -  'Overdriven Guitar': '加驱动效果的电吉他',
 | 
	
		
			
				|  |  | -  'Distortion Guitar': '加失真效果的电吉他',
 | 
	
		
			
				|  |  | -  'Guitar Harmonics': '吉他和音',
 | 
	
		
			
				|  |  | -  'Acoustic Bass': '大贝司',
 | 
	
		
			
				|  |  | -  'Electric Bass': '电贝司',
 | 
	
		
			
				|  |  | -  'Fretless Bass': '无品贝司',
 | 
	
		
			
				|  |  | -  'Slap Bass': '掌击',
 | 
	
		
			
				|  |  | -  'Synth Bass': '电子合成',
 | 
	
		
			
				|  |  | -  Violin: '小提琴',
 | 
	
		
			
				|  |  | -  Viola: '中提琴',
 | 
	
		
			
				|  |  | -  Cello: '大提琴',
 | 
	
		
			
				|  |  | -  Contrabass: '低音大提琴',
 | 
	
		
			
				|  |  | -  'Tremolo Strings': '弦乐群颤音音色',
 | 
	
		
			
				|  |  | -  'Pizzicato Strings': '弦乐群拨弦音色',
 | 
	
		
			
				|  |  | -  'Orchestral Harp': '竖琴',
 | 
	
		
			
				|  |  | -  Timpani: '定音鼓',
 | 
	
		
			
				|  |  | -  'String Ensemble': '弦乐合奏音色',
 | 
	
		
			
				|  |  | -  'Synth Strings': '合成弦乐合奏音色',
 | 
	
		
			
				|  |  | -  'Choir Aahs': '人声合唱',
 | 
	
		
			
				|  |  | -  'Voice Oohs': '人声',
 | 
	
		
			
				|  |  | -  'Synth Voice': '合成人声',
 | 
	
		
			
				|  |  | -  'Orchestra Hit': '管弦乐敲击齐奏',
 | 
	
		
			
				|  |  | -  Trumpet: '小号',
 | 
	
		
			
				|  |  | -  Trombone: '长号',
 | 
	
		
			
				|  |  | -  Tuba: '大号',
 | 
	
		
			
				|  |  | -  'Muted Trumpet': '加弱音器小号',
 | 
	
		
			
				|  |  | -  'French Horn': '法国号',
 | 
	
		
			
				|  |  | -  'Brass Section': '铜管组',
 | 
	
		
			
				|  |  | -  'Synth Brass': '合成铜管音色',
 | 
	
		
			
				|  |  | -  'Soprano Sax': '高音萨克斯管',
 | 
	
		
			
				|  |  | -  'Alto Sax': '中音萨克斯管',
 | 
	
		
			
				|  |  | -  'Tenor Sax': '次中音萨克斯管',
 | 
	
		
			
				|  |  | -  'Baritone Sax': '低音萨克斯管',
 | 
	
		
			
				|  |  | -  Oboe: '双簧管',
 | 
	
		
			
				|  |  | -  'English Horn': '英国管',
 | 
	
		
			
				|  |  | -  Bassoon: '巴松',
 | 
	
		
			
				|  |  | -  Clarinet: '单簧管',
 | 
	
		
			
				|  |  | -  'Soprano Saxophone': '高音萨克斯管',
 | 
	
		
			
				|  |  | -  'Alto Saxophone': '中音萨克斯管',
 | 
	
		
			
				|  |  | -  'Tenor Saxophone': '次中音萨克斯管',
 | 
	
		
			
				|  |  | -  'Baritone Saxophone': '低音萨克斯管',
 | 
	
		
			
				|  |  | -  Piccolo: '短笛',
 | 
	
		
			
				|  |  | -  Flute: '长笛',
 | 
	
		
			
				|  |  | -  Recorder: '竖笛',
 | 
	
		
			
				|  |  | -  'Soprano Recorder': '高音竖笛',
 | 
	
		
			
				|  |  | -  'Pan Flute': '排箫',
 | 
	
		
			
				|  |  | -  'Bottle Blow': '瓶木管',
 | 
	
		
			
				|  |  | -  Whistle: '口哨声',
 | 
	
		
			
				|  |  | -  Ocarina: '陶笛',
 | 
	
		
			
				|  |  | -  Lead: '合成主音',
 | 
	
		
			
				|  |  | -  'Lead lead': '合成主音',
 | 
	
		
			
				|  |  | -  'Pad age': '合成音色',
 | 
	
		
			
				|  |  | -  Pad: '合成音色',
 | 
	
		
			
				|  |  | -  FX: '合成效果  科幻',
 | 
	
		
			
				|  |  | -  Sitar: '西塔尔',
 | 
	
		
			
				|  |  | -  Banjo: '班卓琴',
 | 
	
		
			
				|  |  | -  Shamisen: '三昧线',
 | 
	
		
			
				|  |  | -  Koto: '十三弦筝',
 | 
	
		
			
				|  |  | -  Kalimba: '卡林巴',
 | 
	
		
			
				|  |  | -  Bagpipe: '风笛',
 | 
	
		
			
				|  |  | -  Fiddle: '民族提琴',
 | 
	
		
			
				|  |  | -  Shanai: '山奈',
 | 
	
		
			
				|  |  | -  'Tinkle Bell': '叮当铃',
 | 
	
		
			
				|  |  | -  Agogos: '阿戈戈铃',
 | 
	
		
			
				|  |  | -  'Steel Drums': '钢鼓',
 | 
	
		
			
				|  |  | -  'Taiko Drum': '太鼓',
 | 
	
		
			
				|  |  | -  'Melodic Toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | -  'Synth Drums': '合成鼓',
 | 
	
		
			
				|  |  | -  'Reverse Cymbals': '反向镲',
 | 
	
		
			
				|  |  | -  'Agogo Bells': '阿戈戈铃',
 | 
	
		
			
				|  |  | -  'Taiko Drums': '太鼓',
 | 
	
		
			
				|  |  | -  Bongos: '邦戈鼓',
 | 
	
		
			
				|  |  | -  'Bongo Bell': '邦戈铃',
 | 
	
		
			
				|  |  | -  Congas: '康加鼓',
 | 
	
		
			
				|  |  | -  Guiro: '刮壶',
 | 
	
		
			
				|  |  | -  'Guitar Fret Noise': '吉他换把杂音',
 | 
	
		
			
				|  |  | -  'Breath Noise': '呼吸声',
 | 
	
		
			
				|  |  | -  Seashore: '海浪声',
 | 
	
		
			
				|  |  | -  'Bird Tweet': '鸟鸣',
 | 
	
		
			
				|  |  | -  'Telephone Ring': '电话铃',
 | 
	
		
			
				|  |  | -  Helicopter: '直升机',
 | 
	
		
			
				|  |  | -  Applause: '鼓掌声',
 | 
	
		
			
				|  |  | -  Gunshot: '枪声',
 | 
	
		
			
				|  |  | -  'Acoustic Bass Drum': '大鼓',
 | 
	
		
			
				|  |  | -  'Bass Drum': '大鼓',
 | 
	
		
			
				|  |  | -  'Side Drum': '小鼓鼓边',
 | 
	
		
			
				|  |  | -  'Acoustic Snare': '小鼓',
 | 
	
		
			
				|  |  | -  'Hand Claps': '拍手',
 | 
	
		
			
				|  |  | -  'Electric Snare': '小鼓',
 | 
	
		
			
				|  |  | -  'Low Floor Tom': '低音嗵鼓',
 | 
	
		
			
				|  |  | -  'Closed Hi-Hat': '闭合踩镲',
 | 
	
		
			
				|  |  | -  'High Floor Tom': '高音落地嗵鼓',
 | 
	
		
			
				|  |  | -  'Pedal Hi-Hat': '脚踏踩镲',
 | 
	
		
			
				|  |  | -  'Low Tom': '低音嗵鼓',
 | 
	
		
			
				|  |  | -  'Open Hi-Hat': '开音踩镲',
 | 
	
		
			
				|  |  | -  'Low-Mid Tom': '中低音嗵鼓',
 | 
	
		
			
				|  |  | -  'Hi Mid Tom': '高音鼓',
 | 
	
		
			
				|  |  | -  'Crash Cymbals': '对镲',
 | 
	
		
			
				|  |  | -  'High Tom': '高音嗵鼓',
 | 
	
		
			
				|  |  | -  'Ride Cymbals': '叮叮镲',
 | 
	
		
			
				|  |  | -  'Chinese Cymbals': '中国镲',
 | 
	
		
			
				|  |  | -  'Ride Bell': '圆铃',
 | 
	
		
			
				|  |  | -  Tambourine: '铃鼓',
 | 
	
		
			
				|  |  | -  'Splash Cymbal': '溅音镲',
 | 
	
		
			
				|  |  | -  Cowbell: '牛铃',
 | 
	
		
			
				|  |  | -  'Crash Cymbal': '强音钹',
 | 
	
		
			
				|  |  | -  'Vibra-Slap': '颤音器',
 | 
	
		
			
				|  |  | -  'Ride Cymbal': '打点钹',
 | 
	
		
			
				|  |  | -  'Hi Bongo': '高音邦戈鼓',
 | 
	
		
			
				|  |  | -  'Low Bongo': '低音邦戈鼓',
 | 
	
		
			
				|  |  | -  'Mute Hi Conga': '弱音高音康加鼓',
 | 
	
		
			
				|  |  | -  'Open Hi Conga': '强音高音康加鼓',
 | 
	
		
			
				|  |  | -  'Low Conga': '低音康加鼓',
 | 
	
		
			
				|  |  | -  'High Timbale': '高音天巴鼓',
 | 
	
		
			
				|  |  | -  'Low Timbale': '低音天巴鼓',
 | 
	
		
			
				|  |  | -  'High Agogo': '高音阿戈戈铃',
 | 
	
		
			
				|  |  | -  'Low Agogo': '低音阿戈戈铃',
 | 
	
		
			
				|  |  | -  Cabasa: '卡巴萨',
 | 
	
		
			
				|  |  | -  Maracas: '沙锤',
 | 
	
		
			
				|  |  | -  'Short Whistle': '短口哨',
 | 
	
		
			
				|  |  | -  'Long Whistle': '长口哨',
 | 
	
		
			
				|  |  | -  'Short Guiro': '短刮壶',
 | 
	
		
			
				|  |  | -  'Long Guiro': '长刮壶',
 | 
	
		
			
				|  |  | -  Claves: '响棒',
 | 
	
		
			
				|  |  | -  'Hi Wood Block': '高音木鱼',
 | 
	
		
			
				|  |  | -  'Low Wood Block': '低音木鱼',
 | 
	
		
			
				|  |  | -  'Mute Triangle': '弱音三角铁',
 | 
	
		
			
				|  |  | -  'Open Triangle': '强音三角铁',
 | 
	
		
			
				|  |  | -  'Drum Set': '架子鼓',
 | 
	
		
			
				|  |  | -  'Hulusi flute': '葫芦丝',
 | 
	
		
			
				|  |  | -  Melodica: '口风琴',
 | 
	
		
			
				|  |  | -  Nai: '口风琴',
 | 
	
		
			
				|  |  | -  'Snare Drum': '小军鼓',
 | 
	
		
			
				|  |  | -  Cymbal: '镲',
 | 
	
		
			
				|  |  | -  Cymbals: '镲',
 | 
	
		
			
				|  |  | -  'Horn in F': '圆号',
 | 
	
		
			
				|  |  | -  Triangle: '三角铁',
 | 
	
		
			
				|  |  | -  Vibrato: '颤音琴',
 | 
	
		
			
				|  |  | -  'Suspend Cymbals': '吊镲',
 | 
	
		
			
				|  |  | -  'Suspended Cymbals': '吊镲',
 | 
	
		
			
				|  |  | -  'Tom-Toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | -  Bell: '铃铛',
 | 
	
		
			
				|  |  | -  Bells: '铃铛',
 | 
	
		
			
				|  |  | -  'Alto Clarinet': '中音单簧管',
 | 
	
		
			
				|  |  | -  'Bass Clarinet': '低音单簧管',
 | 
	
		
			
				|  |  | -  Cornet: '短号',
 | 
	
		
			
				|  |  | -  Euphonium: '上低音号',
 | 
	
		
			
				|  |  | -  'crash cymbals': '对镲',
 | 
	
		
			
				|  |  | -  Castanets: '响板',
 | 
	
		
			
				|  |  | -  Shaker: '沙锤',
 | 
	
		
			
				|  |  | -  'Mark tree': '音树',
 | 
	
		
			
				|  |  | -  Chimes: '管钟',
 | 
	
		
			
				|  |  | -  'Mark Tree': '音树',
 | 
	
		
			
				|  |  | -  'Tom-toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | -  'Hi-Hat': '踩镲',
 | 
	
		
			
				|  |  | -  'Sleigh Bells': '雪橇铃',
 | 
	
		
			
				|  |  | -  Flexatone: '弹音器',
 | 
	
		
			
				|  |  | -  'Brake drum': '闸鼓',
 | 
	
		
			
				|  |  | -  Gong: '锣',
 | 
	
		
			
				|  |  | -  'concert tom': '音乐会嗵嗵鼓',
 | 
	
		
			
				|  |  | -  'brake drum': '车轮鼓',
 | 
	
		
			
				|  |  | -  'finger cymbal': '指钹',
 | 
	
		
			
				|  |  | -  'ride cymbal': '叮叮镲',
 | 
	
		
			
				|  |  | -  'Concert Toms': '音乐会嗵嗵鼓',
 | 
	
		
			
				|  |  | -  Vibraslap: '弹音器',
 | 
	
		
			
				|  |  | -  'Wood Blocks': '木鱼',
 | 
	
		
			
				|  |  | -  'Temple Blocks': '木鱼',
 | 
	
		
			
				|  |  | -  'Wood Block': '木鱼',
 | 
	
		
			
				|  |  | -  'Field Drum': '军鼓',
 | 
	
		
			
				|  |  | -  'Quad-Toms': '筒鼓',
 | 
	
		
			
				|  |  | -  Quads: '筒鼓',
 | 
	
		
			
				|  |  | -  'Drums set': '架子鼓',
 | 
	
		
			
				|  |  | -  'High Bongo': '邦戈',
 | 
	
		
			
				|  |  | -  Timbales: '天巴鼓'
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** 获取分轨名称 */
 | 
	
		
			
				|  |  | -export const getInstrumentName = (name = '') => {
 | 
	
		
			
				|  |  | -  name = name.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | -  if (!name) return '';
 | 
	
		
			
				|  |  | -  for (const key in instruments) {
 | 
	
		
			
				|  |  | -    const _key = key.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | -    if (_key.includes(name)) {
 | 
	
		
			
				|  |  | -      return instruments[key];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  for (const key in instruments) {
 | 
	
		
			
				|  |  | -    const _key = key.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | -    if (name.includes(_key)) {
 | 
	
		
			
				|  |  | -      return instruments[key];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return '';
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * 乐器排序
 | 
	
		
			
				|  |  | - * 排序顺序:长笛、单簧管、中音单簧管、低音单簧管、高音萨克斯风、中音萨克斯风、次中音萨克斯风、低音萨克斯风、小号、长号、圆号、大号、上低音号
 | 
	
		
			
				|  |  | - * */
 | 
	
		
			
				|  |  | -export const sortMusical = (name: string, index: number) => {
 | 
	
		
			
				|  |  | -  let sortId = 0;
 | 
	
		
			
				|  |  | -  switch (name) {
 | 
	
		
			
				|  |  | -    case '长笛':
 | 
	
		
			
				|  |  | -      sortId = 1;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '单簧管':
 | 
	
		
			
				|  |  | -      sortId = 2;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '中音单簧管':
 | 
	
		
			
				|  |  | -      sortId = 3;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '低音单簧管':
 | 
	
		
			
				|  |  | -      sortId = 4;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '高音萨克斯风':
 | 
	
		
			
				|  |  | -      sortId = 5;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '中音萨克斯风':
 | 
	
		
			
				|  |  | -      sortId = 6;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '次中音萨克斯风':
 | 
	
		
			
				|  |  | -      sortId = 7;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '低音萨克斯风':
 | 
	
		
			
				|  |  | -      sortId = 8;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '小号':
 | 
	
		
			
				|  |  | -      sortId = 9;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '长号':
 | 
	
		
			
				|  |  | -      sortId = 10;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '圆号':
 | 
	
		
			
				|  |  | -      sortId = 11;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '大号':
 | 
	
		
			
				|  |  | -      sortId = 12;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    case '上低音号':
 | 
	
		
			
				|  |  | -      sortId = 13;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    default:
 | 
	
		
			
				|  |  | -      sortId = index + 14;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return sortId;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// 课堂乐器声轨名称集合
 | 
	
		
			
				|  |  | -const trackNames: any = {
 | 
	
		
			
				|  |  | -  Piccolo: 'Tenor Recorder',
 | 
	
		
			
				|  |  | -  flute: 'Flute',
 | 
	
		
			
				|  |  | -  Flute: 'Flute',
 | 
	
		
			
				|  |  | -  'Flute 1': 'Flute',
 | 
	
		
			
				|  |  | -  'Flute 2': 'Flute',
 | 
	
		
			
				|  |  | -  Oboe: 'Clarinet',
 | 
	
		
			
				|  |  | -  oboe: 'Clarinet',
 | 
	
		
			
				|  |  | -  clarinet: 'Clarinet',
 | 
	
		
			
				|  |  | -  'Clarinet in Bb': 'Clarinet',
 | 
	
		
			
				|  |  | -  'Clarinet in Bb 1': 'Clarinet',
 | 
	
		
			
				|  |  | -  'Clarinet in Bb 2': 'Clarinet',
 | 
	
		
			
				|  |  | -  'Alto Clarinet in Eb': 'Clarinet',
 | 
	
		
			
				|  |  | -  'Bass Clarinet in Bb': 'Clarinet',
 | 
	
		
			
				|  |  | -  Bassoon: 'Bassoon',
 | 
	
		
			
				|  |  | -  'Alto Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  'Tenor Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  'Baritone Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  altosaxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  tenorsaxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  saxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | -  'Trumpet in Bb 1': 'Trumpet',
 | 
	
		
			
				|  |  | -  'Trumpet in Bb 2': 'Trumpet',
 | 
	
		
			
				|  |  | -  trumpet: 'Trumpet',
 | 
	
		
			
				|  |  | -  'Horn in F': 'Horn',
 | 
	
		
			
				|  |  | -  'Horn in F 1': 'Horn',
 | 
	
		
			
				|  |  | -  'Horn in F 2': 'Horn',
 | 
	
		
			
				|  |  | -  horn: 'Horn',
 | 
	
		
			
				|  |  | -  trombone: 'Trombone',
 | 
	
		
			
				|  |  | -  'Trombone 1': 'Trombone',
 | 
	
		
			
				|  |  | -  'Trombone 2': 'Trombone',
 | 
	
		
			
				|  |  | -  'Trombone 3': 'Trombone',
 | 
	
		
			
				|  |  | -  Euphonium: 'Baritone',
 | 
	
		
			
				|  |  | -  upbasshorn: 'Baritone',
 | 
	
		
			
				|  |  | -  Tuba: 'Tuba',
 | 
	
		
			
				|  |  | -  tuba: 'Tuba',
 | 
	
		
			
				|  |  | -  Chimes: 'Chimes',
 | 
	
		
			
				|  |  | -  Bells: 'Bells',
 | 
	
		
			
				|  |  | -  Xylophone: 'Xylophone',
 | 
	
		
			
				|  |  | -  'Snare Drum': 'Snare Drum',
 | 
	
		
			
				|  |  | -  'Bass Drum': 'Bass Drum',
 | 
	
		
			
				|  |  | -  Triangle: 'Triangle',
 | 
	
		
			
				|  |  | -  'Suspended Cymbal': 'Suspended Cymbal',
 | 
	
		
			
				|  |  | -  'Crash Cymbals': 'Crash Cymbals',
 | 
	
		
			
				|  |  | -  'Concert Toms': 'Concert Toms',
 | 
	
		
			
				|  |  | -  Timpani: 'Timpani',
 | 
	
		
			
				|  |  | -  'Drum Set': 'Drum Set',
 | 
	
		
			
				|  |  | -  Marimba: 'Marimba',
 | 
	
		
			
				|  |  | -  Vibraphone: 'Vibraphone',
 | 
	
		
			
				|  |  | -  'Tubular Bells': 'Tubular Bells',
 | 
	
		
			
				|  |  | -  Mallets: 'Mallets',
 | 
	
		
			
				|  |  | -  recorder: 'Piccolo',
 | 
	
		
			
				|  |  | -  tenorrecorder: 'piccolo',
 | 
	
		
			
				|  |  | -  melodica: 'melodica',
 | 
	
		
			
				|  |  | -  hulusiFlute: 'hulusiFlute',
 | 
	
		
			
				|  |  | -  panflute: 'panflute',
 | 
	
		
			
				|  |  | -  ukulele: 'ukulele',
 | 
	
		
			
				|  |  | -  mouthorgan: 'mouthorgan',
 | 
	
		
			
				|  |  | -  piano: 'piano',
 | 
	
		
			
				|  |  | -  woodwind: 'Woodwind',
 | 
	
		
			
				|  |  | -  panpipes: 'Panpipes',
 | 
	
		
			
				|  |  | -  ocarina: 'Ocarina',
 | 
	
		
			
				|  |  | -  nai: 'Nai',
 | 
	
		
			
				|  |  | -  BaroqueRecorder: 'Baroque Recorder'
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** 声轨track转换成乐器code */
 | 
	
		
			
				|  |  | -export const trackToCode = (track: any) => {
 | 
	
		
			
				|  |  | -  return trackNames[track] || track;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -export const iframeDislableKeyboard = (iframeDom: any) => {
 | 
	
		
			
				|  |  | -  // 在 iframe 内部注入脚本禁用右键菜单
 | 
	
		
			
				|  |  | -  const script = document.createElement('script');
 | 
	
		
			
				|  |  | -  script.innerHTML = `
 | 
	
		
			
				|  |  | -      document.addEventListener('contextmenu', function(e) {
 | 
	
		
			
				|  |  | -          e.preventDefault();
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      document.addEventListener('keydown', function (event) {
 | 
	
		
			
				|  |  | -        // 屏蔽 F12 和 Ctrl+Shift+I
 | 
	
		
			
				|  |  | -        if (
 | 
	
		
			
				|  |  | -          event.key === 'F12' ||
 | 
	
		
			
				|  |  | -          (event.ctrlKey && event.shiftKey && event.key === 'I') ||
 | 
	
		
			
				|  |  | -          (event.metaKey && event.altKey && event.key === 'I')
 | 
	
		
			
				|  |  | -        ) {
 | 
	
		
			
				|  |  | -          event.preventDefault();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      });
 | 
	
		
			
				|  |  | -            `;
 | 
	
		
			
				|  |  | -  if (iframeDom.contentWindow.document.body) {
 | 
	
		
			
				|  |  | -    iframeDom?.contentDocument?.body.appendChild(script);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +import { h, unref } from 'vue';
 | 
	
		
			
				|  |  | +import type { App, Plugin } from 'vue';
 | 
	
		
			
				|  |  | +import { NIcon, NTag } from 'naive-ui';
 | 
	
		
			
				|  |  | +import { PageEnum } from '@/enums/pageEnum';
 | 
	
		
			
				|  |  | +import { isObject } from './is/index';
 | 
	
		
			
				|  |  | +import { cloneDeep } from 'lodash';
 | 
	
		
			
				|  |  | +import dayjs from 'dayjs';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import EventEmitter from 'eventemitter3';
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const eventGlobal = new EventEmitter();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * render 图标
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function renderIcon(icon: any) {
 | 
	
		
			
				|  |  | +  return () => h(NIcon, null, { default: () => h(icon) });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * font 图标(Font class)
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function renderFontClassIcon(icon: string, iconName = 'iconfont') {
 | 
	
		
			
				|  |  | +  return () => h('span', { class: [iconName, icon] });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * font 图标(Unicode)
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function renderUnicodeIcon(icon: string, iconName = 'iconfont') {
 | 
	
		
			
				|  |  | +  return () => h('span', { class: [iconName], innerHTML: icon });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * font svg 图标
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function renderfontsvg(icon: any) {
 | 
	
		
			
				|  |  | +  return () =>
 | 
	
		
			
				|  |  | +    h(NIcon, null, {
 | 
	
		
			
				|  |  | +      default: () =>
 | 
	
		
			
				|  |  | +        h(
 | 
	
		
			
				|  |  | +          'svg',
 | 
	
		
			
				|  |  | +          { class: `icon`, 'aria-hidden': 'true' },
 | 
	
		
			
				|  |  | +          h('use', { 'xlink:href': `#${icon}` })
 | 
	
		
			
				|  |  | +        )
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * render new Tag
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' };
 | 
	
		
			
				|  |  | +export function renderNew(
 | 
	
		
			
				|  |  | +  type = 'warning',
 | 
	
		
			
				|  |  | +  text = 'New',
 | 
	
		
			
				|  |  | +  color: object = newTagColors
 | 
	
		
			
				|  |  | +) {
 | 
	
		
			
				|  |  | +  return () =>
 | 
	
		
			
				|  |  | +    h(
 | 
	
		
			
				|  |  | +      NTag as any,
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +        type,
 | 
	
		
			
				|  |  | +        round: true,
 | 
	
		
			
				|  |  | +        size: 'small',
 | 
	
		
			
				|  |  | +        color
 | 
	
		
			
				|  |  | +      },
 | 
	
		
			
				|  |  | +      { default: () => text }
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 递归组装菜单格式
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +export function generatorMenu(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | +  return filterRouter(routerMap).map(item => {
 | 
	
		
			
				|  |  | +    const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | +    if (isRoot) {
 | 
	
		
			
				|  |  | +      console.log(item.children[0], 'isRoot');
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | +    // console.log(item)
 | 
	
		
			
				|  |  | +    const currentMenu = {
 | 
	
		
			
				|  |  | +      ...info,
 | 
	
		
			
				|  |  | +      ...info.meta,
 | 
	
		
			
				|  |  | +      label: info.meta?.title,
 | 
	
		
			
				|  |  | +      key: info.key,
 | 
	
		
			
				|  |  | +      icon: info.meta?.icon
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    // 是否有子菜单,并递归处理
 | 
	
		
			
				|  |  | +    if (info.children && info.children.length > 0) {
 | 
	
		
			
				|  |  | +      // Recursion
 | 
	
		
			
				|  |  | +      currentMenu.children = generatorMenu(info.children);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return currentMenu;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 混合菜单
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function generatorMenuMix(
 | 
	
		
			
				|  |  | +  routerMap: Array<any>,
 | 
	
		
			
				|  |  | +  routerName: string,
 | 
	
		
			
				|  |  | +  location: string
 | 
	
		
			
				|  |  | +) {
 | 
	
		
			
				|  |  | +  const cloneRouterMap = cloneDeep(routerMap);
 | 
	
		
			
				|  |  | +  const newRouter = filterRouter(cloneRouterMap);
 | 
	
		
			
				|  |  | +  if (location === 'header') {
 | 
	
		
			
				|  |  | +    const firstRouter: any[] = [];
 | 
	
		
			
				|  |  | +    newRouter.forEach(item => {
 | 
	
		
			
				|  |  | +      const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | +      const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | +      info.children = undefined;
 | 
	
		
			
				|  |  | +      const currentMenu = {
 | 
	
		
			
				|  |  | +        ...info,
 | 
	
		
			
				|  |  | +        ...info.meta,
 | 
	
		
			
				|  |  | +        label: info.meta?.title,
 | 
	
		
			
				|  |  | +        key: info.name
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +      firstRouter.push(currentMenu);
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return firstRouter;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    // 混合菜单
 | 
	
		
			
				|  |  | +    console.log('混合菜单');
 | 
	
		
			
				|  |  | +    return getChildrenRouter(
 | 
	
		
			
				|  |  | +      newRouter.filter(item => item.name === routerName)
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 递归组装子菜单
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function getChildrenRouter(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | +  return filterRouter(routerMap).map(item => {
 | 
	
		
			
				|  |  | +    const isRoot = isRootRouter(item);
 | 
	
		
			
				|  |  | +    const info = isRoot ? item.children[0] : item;
 | 
	
		
			
				|  |  | +    const currentMenu = {
 | 
	
		
			
				|  |  | +      ...info,
 | 
	
		
			
				|  |  | +      ...info.meta,
 | 
	
		
			
				|  |  | +      label: info.meta?.title,
 | 
	
		
			
				|  |  | +      key: info.name
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    // 是否有子菜单,并递归处理
 | 
	
		
			
				|  |  | +    if (info.children && info.children.length > 0) {
 | 
	
		
			
				|  |  | +      // Recursion
 | 
	
		
			
				|  |  | +      currentMenu.children = getChildrenRouter(info.children);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return currentMenu;
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 判断根路由 Router
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function isRootRouter(item: any) {
 | 
	
		
			
				|  |  | +  return item.meta?.isRoot === true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 排除Router
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function filterRouter(routerMap: Array<any>) {
 | 
	
		
			
				|  |  | +  return routerMap.filter(item => {
 | 
	
		
			
				|  |  | +    // console.log(
 | 
	
		
			
				|  |  | +    //   (item.meta?.hidden || false) != true &&
 | 
	
		
			
				|  |  | +    //   !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path),
 | 
	
		
			
				|  |  | +    //   '过滤完之后的路由'
 | 
	
		
			
				|  |  | +    // )
 | 
	
		
			
				|  |  | +    return (
 | 
	
		
			
				|  |  | +      (item.meta?.hidden || false) != true &&
 | 
	
		
			
				|  |  | +      !['/:path(.*)*', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(
 | 
	
		
			
				|  |  | +        item.path
 | 
	
		
			
				|  |  | +      )
 | 
	
		
			
				|  |  | +    );
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const withInstall = <T>(component: T, alias?: string) => {
 | 
	
		
			
				|  |  | +  const comp = component as any;
 | 
	
		
			
				|  |  | +  comp.install = (app: App) => {
 | 
	
		
			
				|  |  | +    app.component(comp.name || comp.displayName, component as any);
 | 
	
		
			
				|  |  | +    if (alias) {
 | 
	
		
			
				|  |  | +      app.config.globalProperties[alias] = component;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  return component as T & Plugin;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + *  找到对应的节点
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +let result = null as any;
 | 
	
		
			
				|  |  | +export function getTreeItem(data: any[], key?: string | number): any {
 | 
	
		
			
				|  |  | +  data.map(item => {
 | 
	
		
			
				|  |  | +    if (item.key === key) {
 | 
	
		
			
				|  |  | +      result = item;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      if (item.children && item.children.length) {
 | 
	
		
			
				|  |  | +        getTreeItem(item.children, key);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  return result;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + *  找到所有节点
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +const treeAll: any[] = [];
 | 
	
		
			
				|  |  | +export function getTreeAll(data: any[]): any[] {
 | 
	
		
			
				|  |  | +  data.map(item => {
 | 
	
		
			
				|  |  | +    treeAll.push(item.key);
 | 
	
		
			
				|  |  | +    if (item.children && item.children.length) {
 | 
	
		
			
				|  |  | +      getTreeAll(item.children);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +  return treeAll;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
 | 
	
		
			
				|  |  | +  let key: string;
 | 
	
		
			
				|  |  | +  for (key in target) {
 | 
	
		
			
				|  |  | +    src[key] = isObject(src[key])
 | 
	
		
			
				|  |  | +      ? deepMerge(src[key], target[key])
 | 
	
		
			
				|  |  | +      : (src[key] = target[key]);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return src;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Sums the passed percentage to the R, G or B of a HEX color
 | 
	
		
			
				|  |  | + * @param {string} color The color to change
 | 
	
		
			
				|  |  | + * @param {number} amount The amount to change the color by
 | 
	
		
			
				|  |  | + * @returns {string} The processed part of the color
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +function addLight(color: string, amount: number) {
 | 
	
		
			
				|  |  | +  const cc = parseInt(color, 16) + amount;
 | 
	
		
			
				|  |  | +  const c = cc > 255 ? 255 : cc;
 | 
	
		
			
				|  |  | +  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * Lightens a 6 char HEX color according to the passed percentage
 | 
	
		
			
				|  |  | + * @param {string} color The color to change
 | 
	
		
			
				|  |  | + * @param {number} amount The amount to change the color by
 | 
	
		
			
				|  |  | + * @returns {string} The processed color represented as HEX
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +export function lighten(color: string, amount: number) {
 | 
	
		
			
				|  |  | +  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
 | 
	
		
			
				|  |  | +  amount = Math.trunc((255 * amount) / 100);
 | 
	
		
			
				|  |  | +  return `#${addLight(color.substring(0, 2), amount)}${addLight(
 | 
	
		
			
				|  |  | +    color.substring(2, 4),
 | 
	
		
			
				|  |  | +    amount
 | 
	
		
			
				|  |  | +  )}${addLight(color.substring(4, 6), amount)}`;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 判断是否 url
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export function isUrl(url: string) {
 | 
	
		
			
				|  |  | +  return /^(http|https):\/\//g.test(url);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 递归清除空数据 */
 | 
	
		
			
				|  |  | +export function clearEmtryData(list: any[], key: string) {
 | 
	
		
			
				|  |  | +  for (let i = 0; i < list.length; i++) {
 | 
	
		
			
				|  |  | +    if (Array.isArray(list[i][key]) && !list[i][key].length) {
 | 
	
		
			
				|  |  | +      list[i][key] = '';
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      list[i][key] = clearEmtryData(list[i][key], key);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return list;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 秒转分
 | 
	
		
			
				|  |  | +export const getSecondRPM = (second: number, type?: string) => {
 | 
	
		
			
				|  |  | +  if (isNaN(second)) return '00:00';
 | 
	
		
			
				|  |  | +  const mm = Math.floor(second / 60)
 | 
	
		
			
				|  |  | +    .toString()
 | 
	
		
			
				|  |  | +    .padStart(2, '0');
 | 
	
		
			
				|  |  | +  const dd = Math.floor(second % 60)
 | 
	
		
			
				|  |  | +    .toString()
 | 
	
		
			
				|  |  | +    .padStart(2, '0');
 | 
	
		
			
				|  |  | +  if (type === 'cn') {
 | 
	
		
			
				|  |  | +    return mm + '分' + dd + '秒';
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return mm + ':' + dd;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 秒转分
 | 
	
		
			
				|  |  | +export const getSecond = (second: number, type?: string) => {
 | 
	
		
			
				|  |  | +  if (isNaN(second)) return '0000';
 | 
	
		
			
				|  |  | +  const mm = Math.floor(second / 60)
 | 
	
		
			
				|  |  | +    .toString()
 | 
	
		
			
				|  |  | +    .padStart(2, '0');
 | 
	
		
			
				|  |  | +  const dd = Math.floor(second % 60)
 | 
	
		
			
				|  |  | +    .toString()
 | 
	
		
			
				|  |  | +    .padStart(2, '0');
 | 
	
		
			
				|  |  | +  return `${mm}${dd}`;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 滚动到表单填写错误的地方 */
 | 
	
		
			
				|  |  | +export function scrollToErrorForm() {
 | 
	
		
			
				|  |  | +  const isError =
 | 
	
		
			
				|  |  | +    document.querySelector('.n-input--error-status') ||
 | 
	
		
			
				|  |  | +    document.querySelector('.n-base-selection--error-status');
 | 
	
		
			
				|  |  | +  isError?.scrollIntoView({
 | 
	
		
			
				|  |  | +    block: 'center',
 | 
	
		
			
				|  |  | +    behavior: 'smooth'
 | 
	
		
			
				|  |  | +  });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const getTimes = (
 | 
	
		
			
				|  |  | +  times: any,
 | 
	
		
			
				|  |  | +  keys: Array<string> = [],
 | 
	
		
			
				|  |  | +  format = 'YYYY-MM-DD'
 | 
	
		
			
				|  |  | +) => {
 | 
	
		
			
				|  |  | +  if (times && times.length) {
 | 
	
		
			
				|  |  | +    return format == 'YYYY-MM-DD'
 | 
	
		
			
				|  |  | +      ? {
 | 
	
		
			
				|  |  | +        [keys[0] || 'start']: dayjs(times[0]).isValid()
 | 
	
		
			
				|  |  | +          ? dayjs(times[0]).format(format) + ' 00:00:00'
 | 
	
		
			
				|  |  | +          : '',
 | 
	
		
			
				|  |  | +        [keys[1] || 'end']: dayjs(times[1]).isValid()
 | 
	
		
			
				|  |  | +          ? dayjs(times[1]).format(format) + ' 23:59:59'
 | 
	
		
			
				|  |  | +          : ''
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      : {
 | 
	
		
			
				|  |  | +        [keys[0] || 'start']: dayjs(times[0]).isValid()
 | 
	
		
			
				|  |  | +          ? dayjs(times[0]).format(format)
 | 
	
		
			
				|  |  | +          : '',
 | 
	
		
			
				|  |  | +        [keys[1] || 'end']: dayjs(times[1]).isValid()
 | 
	
		
			
				|  |  | +          ? dayjs(times[1]).format(format)
 | 
	
		
			
				|  |  | +          : ''
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return {};
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const px2vw = (px: number): string => `${(px / 1920) * 100}vw`;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const px2vwH = (px: number): string =>
 | 
	
		
			
				|  |  | +  `${(((px / 1920) * 1920) / 1188) * 100}vw`;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +export const fscreen = () => {
 | 
	
		
			
				|  |  | +  const el = document.documentElement;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  //进入全屏
 | 
	
		
			
				|  |  | +  (el.requestFullscreen && el.requestFullscreen()) ||
 | 
	
		
			
				|  |  | +    (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
 | 
	
		
			
				|  |  | +    (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
 | 
	
		
			
				|  |  | +    (el.msRequestFullscreen && el.msRequestFullscreen());
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//退出全屏
 | 
	
		
			
				|  |  | +export const exitFullscreen = () => {
 | 
	
		
			
				|  |  | +  document.exitFullscreen
 | 
	
		
			
				|  |  | +    ? document.exitFullscreen()
 | 
	
		
			
				|  |  | +    : document.mozCancelFullScreen
 | 
	
		
			
				|  |  | +      ? document.mozCancelFullScreen()
 | 
	
		
			
				|  |  | +      : document.webkitExitFullscreen
 | 
	
		
			
				|  |  | +        ? document.webkitExitFullscreen()
 | 
	
		
			
				|  |  | +        : '';
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 检测链接格式 */
 | 
	
		
			
				|  |  | +export function checkUrlType(urlType: string) {
 | 
	
		
			
				|  |  | +  const subfix = (urlType || '').split('.').pop();
 | 
	
		
			
				|  |  | +  if (subfix === 'wav' || subfix === 'mp3' || subfix === 'm4a') {
 | 
	
		
			
				|  |  | +    return 'audio';
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return 'video';
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const instruments: any = {
 | 
	
		
			
				|  |  | +  'Acoustic Grand Piano': '大钢琴',
 | 
	
		
			
				|  |  | +  'Bright Acoustic Piano': '明亮的钢琴',
 | 
	
		
			
				|  |  | +  'Electric Grand Piano': '电钢琴',
 | 
	
		
			
				|  |  | +  'Rhodes Piano': '柔和的电钢琴',
 | 
	
		
			
				|  |  | +  'Chorused Piano': '加合唱效果的电钢琴',
 | 
	
		
			
				|  |  | +  Harpsichord: '羽管键琴',
 | 
	
		
			
				|  |  | +  Clavichord: '科拉维科特琴',
 | 
	
		
			
				|  |  | +  Celesta: '钢片琴',
 | 
	
		
			
				|  |  | +  Glockenspiel: '钢片琴',
 | 
	
		
			
				|  |  | +  'Music box': '八音盒',
 | 
	
		
			
				|  |  | +  Vibraphone: '颤音琴',
 | 
	
		
			
				|  |  | +  Marimba: '马林巴',
 | 
	
		
			
				|  |  | +  Xylophone: '木琴',
 | 
	
		
			
				|  |  | +  'Tubular Bells': '管钟',
 | 
	
		
			
				|  |  | +  Dulcimer: '大扬琴',
 | 
	
		
			
				|  |  | +  'Hammond Organ': '击杆风琴',
 | 
	
		
			
				|  |  | +  'Percussive Organ': '打击式风琴',
 | 
	
		
			
				|  |  | +  'Rock Organ': '摇滚风琴',
 | 
	
		
			
				|  |  | +  'Church Organ': '教堂风琴',
 | 
	
		
			
				|  |  | +  'Reed Organ': '簧管风琴',
 | 
	
		
			
				|  |  | +  Accordian: '手风琴',
 | 
	
		
			
				|  |  | +  Harmonica: '口琴',
 | 
	
		
			
				|  |  | +  'Tango Accordian': '探戈手风琴',
 | 
	
		
			
				|  |  | +  'Acoustic Guitar': '钢弦吉他',
 | 
	
		
			
				|  |  | +  'Electric Guitar': '闷音电吉他',
 | 
	
		
			
				|  |  | +  'Overdriven Guitar': '加驱动效果的电吉他',
 | 
	
		
			
				|  |  | +  'Distortion Guitar': '加失真效果的电吉他',
 | 
	
		
			
				|  |  | +  'Guitar Harmonics': '吉他和音',
 | 
	
		
			
				|  |  | +  'Acoustic Bass': '大贝司',
 | 
	
		
			
				|  |  | +  'Electric Bass': '电贝司',
 | 
	
		
			
				|  |  | +  'Fretless Bass': '无品贝司',
 | 
	
		
			
				|  |  | +  'Slap Bass': '掌击',
 | 
	
		
			
				|  |  | +  'Synth Bass': '电子合成',
 | 
	
		
			
				|  |  | +  Violin: '小提琴',
 | 
	
		
			
				|  |  | +  Viola: '中提琴',
 | 
	
		
			
				|  |  | +  Cello: '大提琴',
 | 
	
		
			
				|  |  | +  Contrabass: '低音大提琴',
 | 
	
		
			
				|  |  | +  'Tremolo Strings': '弦乐群颤音音色',
 | 
	
		
			
				|  |  | +  'Pizzicato Strings': '弦乐群拨弦音色',
 | 
	
		
			
				|  |  | +  'Orchestral Harp': '竖琴',
 | 
	
		
			
				|  |  | +  Timpani: '定音鼓',
 | 
	
		
			
				|  |  | +  'String Ensemble': '弦乐合奏音色',
 | 
	
		
			
				|  |  | +  'Synth Strings': '合成弦乐合奏音色',
 | 
	
		
			
				|  |  | +  'Choir Aahs': '人声合唱',
 | 
	
		
			
				|  |  | +  'Voice Oohs': '人声',
 | 
	
		
			
				|  |  | +  'Synth Voice': '合成人声',
 | 
	
		
			
				|  |  | +  'Orchestra Hit': '管弦乐敲击齐奏',
 | 
	
		
			
				|  |  | +  Trumpet: '小号',
 | 
	
		
			
				|  |  | +  Trombone: '长号',
 | 
	
		
			
				|  |  | +  Tuba: '大号',
 | 
	
		
			
				|  |  | +  'Muted Trumpet': '加弱音器小号',
 | 
	
		
			
				|  |  | +  'French Horn': '法国号',
 | 
	
		
			
				|  |  | +  'Brass Section': '铜管组',
 | 
	
		
			
				|  |  | +  'Synth Brass': '合成铜管音色',
 | 
	
		
			
				|  |  | +  'Soprano Sax': '高音萨克斯管',
 | 
	
		
			
				|  |  | +  'Alto Sax': '中音萨克斯管',
 | 
	
		
			
				|  |  | +  'Tenor Sax': '次中音萨克斯管',
 | 
	
		
			
				|  |  | +  'Baritone Sax': '低音萨克斯管',
 | 
	
		
			
				|  |  | +  Oboe: '双簧管',
 | 
	
		
			
				|  |  | +  'English Horn': '英国管',
 | 
	
		
			
				|  |  | +  Bassoon: '巴松',
 | 
	
		
			
				|  |  | +  Clarinet: '单簧管',
 | 
	
		
			
				|  |  | +  'Soprano Saxophone': '高音萨克斯管',
 | 
	
		
			
				|  |  | +  'Alto Saxophone': '中音萨克斯管',
 | 
	
		
			
				|  |  | +  'Tenor Saxophone': '次中音萨克斯管',
 | 
	
		
			
				|  |  | +  'Baritone Saxophone': '低音萨克斯管',
 | 
	
		
			
				|  |  | +  Piccolo: '短笛',
 | 
	
		
			
				|  |  | +  Flute: '长笛',
 | 
	
		
			
				|  |  | +  Recorder: '竖笛',
 | 
	
		
			
				|  |  | +  'Soprano Recorder': '高音竖笛',
 | 
	
		
			
				|  |  | +  'Pan Flute': '排箫',
 | 
	
		
			
				|  |  | +  'Bottle Blow': '瓶木管',
 | 
	
		
			
				|  |  | +  Whistle: '口哨声',
 | 
	
		
			
				|  |  | +  Ocarina: '陶笛',
 | 
	
		
			
				|  |  | +  Lead: '合成主音',
 | 
	
		
			
				|  |  | +  'Lead lead': '合成主音',
 | 
	
		
			
				|  |  | +  'Pad age': '合成音色',
 | 
	
		
			
				|  |  | +  Pad: '合成音色',
 | 
	
		
			
				|  |  | +  FX: '合成效果  科幻',
 | 
	
		
			
				|  |  | +  Sitar: '西塔尔',
 | 
	
		
			
				|  |  | +  Banjo: '班卓琴',
 | 
	
		
			
				|  |  | +  Shamisen: '三昧线',
 | 
	
		
			
				|  |  | +  Koto: '十三弦筝',
 | 
	
		
			
				|  |  | +  Kalimba: '卡林巴',
 | 
	
		
			
				|  |  | +  Bagpipe: '风笛',
 | 
	
		
			
				|  |  | +  Fiddle: '民族提琴',
 | 
	
		
			
				|  |  | +  Shanai: '山奈',
 | 
	
		
			
				|  |  | +  'Tinkle Bell': '叮当铃',
 | 
	
		
			
				|  |  | +  Agogos: '阿戈戈铃',
 | 
	
		
			
				|  |  | +  'Steel Drums': '钢鼓',
 | 
	
		
			
				|  |  | +  'Taiko Drum': '太鼓',
 | 
	
		
			
				|  |  | +  'Melodic Toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | +  'Synth Drums': '合成鼓',
 | 
	
		
			
				|  |  | +  'Reverse Cymbals': '反向镲',
 | 
	
		
			
				|  |  | +  'Agogo Bells': '阿戈戈铃',
 | 
	
		
			
				|  |  | +  'Taiko Drums': '太鼓',
 | 
	
		
			
				|  |  | +  Bongos: '邦戈鼓',
 | 
	
		
			
				|  |  | +  'Bongo Bell': '邦戈铃',
 | 
	
		
			
				|  |  | +  Congas: '康加鼓',
 | 
	
		
			
				|  |  | +  Guiro: '刮壶',
 | 
	
		
			
				|  |  | +  'Guitar Fret Noise': '吉他换把杂音',
 | 
	
		
			
				|  |  | +  'Breath Noise': '呼吸声',
 | 
	
		
			
				|  |  | +  Seashore: '海浪声',
 | 
	
		
			
				|  |  | +  'Bird Tweet': '鸟鸣',
 | 
	
		
			
				|  |  | +  'Telephone Ring': '电话铃',
 | 
	
		
			
				|  |  | +  Helicopter: '直升机',
 | 
	
		
			
				|  |  | +  Applause: '鼓掌声',
 | 
	
		
			
				|  |  | +  Gunshot: '枪声',
 | 
	
		
			
				|  |  | +  'Acoustic Bass Drum': '大鼓',
 | 
	
		
			
				|  |  | +  'Bass Drum': '大鼓',
 | 
	
		
			
				|  |  | +  'Side Drum': '小鼓鼓边',
 | 
	
		
			
				|  |  | +  'Acoustic Snare': '小鼓',
 | 
	
		
			
				|  |  | +  'Hand Claps': '拍手',
 | 
	
		
			
				|  |  | +  'Electric Snare': '小鼓',
 | 
	
		
			
				|  |  | +  'Low Floor Tom': '低音嗵鼓',
 | 
	
		
			
				|  |  | +  'Closed Hi-Hat': '闭合踩镲',
 | 
	
		
			
				|  |  | +  'High Floor Tom': '高音落地嗵鼓',
 | 
	
		
			
				|  |  | +  'Pedal Hi-Hat': '脚踏踩镲',
 | 
	
		
			
				|  |  | +  'Low Tom': '低音嗵鼓',
 | 
	
		
			
				|  |  | +  'Open Hi-Hat': '开音踩镲',
 | 
	
		
			
				|  |  | +  'Low-Mid Tom': '中低音嗵鼓',
 | 
	
		
			
				|  |  | +  'Hi Mid Tom': '高音鼓',
 | 
	
		
			
				|  |  | +  'Crash Cymbals': '对镲',
 | 
	
		
			
				|  |  | +  'High Tom': '高音嗵鼓',
 | 
	
		
			
				|  |  | +  'Ride Cymbals': '叮叮镲',
 | 
	
		
			
				|  |  | +  'Chinese Cymbals': '中国镲',
 | 
	
		
			
				|  |  | +  'Ride Bell': '圆铃',
 | 
	
		
			
				|  |  | +  Tambourine: '铃鼓',
 | 
	
		
			
				|  |  | +  'Splash Cymbal': '溅音镲',
 | 
	
		
			
				|  |  | +  Cowbell: '牛铃',
 | 
	
		
			
				|  |  | +  'Crash Cymbal': '强音钹',
 | 
	
		
			
				|  |  | +  'Vibra-Slap': '颤音器',
 | 
	
		
			
				|  |  | +  'Ride Cymbal': '打点钹',
 | 
	
		
			
				|  |  | +  'Hi Bongo': '高音邦戈鼓',
 | 
	
		
			
				|  |  | +  'Low Bongo': '低音邦戈鼓',
 | 
	
		
			
				|  |  | +  'Mute Hi Conga': '弱音高音康加鼓',
 | 
	
		
			
				|  |  | +  'Open Hi Conga': '强音高音康加鼓',
 | 
	
		
			
				|  |  | +  'Low Conga': '低音康加鼓',
 | 
	
		
			
				|  |  | +  'High Timbale': '高音天巴鼓',
 | 
	
		
			
				|  |  | +  'Low Timbale': '低音天巴鼓',
 | 
	
		
			
				|  |  | +  'High Agogo': '高音阿戈戈铃',
 | 
	
		
			
				|  |  | +  'Low Agogo': '低音阿戈戈铃',
 | 
	
		
			
				|  |  | +  Cabasa: '卡巴萨',
 | 
	
		
			
				|  |  | +  Maracas: '沙锤',
 | 
	
		
			
				|  |  | +  'Short Whistle': '短口哨',
 | 
	
		
			
				|  |  | +  'Long Whistle': '长口哨',
 | 
	
		
			
				|  |  | +  'Short Guiro': '短刮壶',
 | 
	
		
			
				|  |  | +  'Long Guiro': '长刮壶',
 | 
	
		
			
				|  |  | +  Claves: '响棒',
 | 
	
		
			
				|  |  | +  'Hi Wood Block': '高音木鱼',
 | 
	
		
			
				|  |  | +  'Low Wood Block': '低音木鱼',
 | 
	
		
			
				|  |  | +  'Mute Triangle': '弱音三角铁',
 | 
	
		
			
				|  |  | +  'Open Triangle': '强音三角铁',
 | 
	
		
			
				|  |  | +  'Drum Set': '架子鼓',
 | 
	
		
			
				|  |  | +  'Hulusi flute': '葫芦丝',
 | 
	
		
			
				|  |  | +  Melodica: '口风琴',
 | 
	
		
			
				|  |  | +  Nai: '口风琴',
 | 
	
		
			
				|  |  | +  'Snare Drum': '小军鼓',
 | 
	
		
			
				|  |  | +  Cymbal: '镲',
 | 
	
		
			
				|  |  | +  Cymbals: '镲',
 | 
	
		
			
				|  |  | +  'Horn in F': '圆号',
 | 
	
		
			
				|  |  | +  Triangle: '三角铁',
 | 
	
		
			
				|  |  | +  Vibrato: '颤音琴',
 | 
	
		
			
				|  |  | +  'Suspend Cymbals': '吊镲',
 | 
	
		
			
				|  |  | +  'Suspended Cymbals': '吊镲',
 | 
	
		
			
				|  |  | +  'Tom-Toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | +  Bell: '铃铛',
 | 
	
		
			
				|  |  | +  Bells: '铃铛',
 | 
	
		
			
				|  |  | +  'Alto Clarinet': '中音单簧管',
 | 
	
		
			
				|  |  | +  'Bass Clarinet': '低音单簧管',
 | 
	
		
			
				|  |  | +  Cornet: '短号',
 | 
	
		
			
				|  |  | +  Euphonium: '上低音号',
 | 
	
		
			
				|  |  | +  'crash cymbals': '对镲',
 | 
	
		
			
				|  |  | +  Castanets: '响板',
 | 
	
		
			
				|  |  | +  Shaker: '沙锤',
 | 
	
		
			
				|  |  | +  'Mark tree': '音树',
 | 
	
		
			
				|  |  | +  Chimes: '管钟',
 | 
	
		
			
				|  |  | +  'Mark Tree': '音树',
 | 
	
		
			
				|  |  | +  'Tom-toms': '嗵嗵鼓',
 | 
	
		
			
				|  |  | +  'Hi-Hat': '踩镲',
 | 
	
		
			
				|  |  | +  'Sleigh Bells': '雪橇铃',
 | 
	
		
			
				|  |  | +  Flexatone: '弹音器',
 | 
	
		
			
				|  |  | +  'Brake drum': '闸鼓',
 | 
	
		
			
				|  |  | +  Gong: '锣',
 | 
	
		
			
				|  |  | +  'concert tom': '音乐会嗵嗵鼓',
 | 
	
		
			
				|  |  | +  'brake drum': '车轮鼓',
 | 
	
		
			
				|  |  | +  'finger cymbal': '指钹',
 | 
	
		
			
				|  |  | +  'ride cymbal': '叮叮镲',
 | 
	
		
			
				|  |  | +  'Concert Toms': '音乐会嗵嗵鼓',
 | 
	
		
			
				|  |  | +  Vibraslap: '弹音器',
 | 
	
		
			
				|  |  | +  'Wood Blocks': '木鱼',
 | 
	
		
			
				|  |  | +  'Temple Blocks': '木鱼',
 | 
	
		
			
				|  |  | +  'Wood Block': '木鱼',
 | 
	
		
			
				|  |  | +  'Field Drum': '军鼓',
 | 
	
		
			
				|  |  | +  'Quad-Toms': '筒鼓',
 | 
	
		
			
				|  |  | +  Quads: '筒鼓',
 | 
	
		
			
				|  |  | +  'Drums set': '架子鼓',
 | 
	
		
			
				|  |  | +  'High Bongo': '邦戈',
 | 
	
		
			
				|  |  | +  Timbales: '天巴鼓'
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 获取分轨名称 */
 | 
	
		
			
				|  |  | +export const getInstrumentName = (name = '') => {
 | 
	
		
			
				|  |  | +  name = name.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | +  if (!name) return '';
 | 
	
		
			
				|  |  | +  for (const key in instruments) {
 | 
	
		
			
				|  |  | +    const _key = key.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | +    if (_key.includes(name)) {
 | 
	
		
			
				|  |  | +      return instruments[key];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  for (const key in instruments) {
 | 
	
		
			
				|  |  | +    const _key = key.toLocaleLowerCase().replace(/ /g, '');
 | 
	
		
			
				|  |  | +    if (name.includes(_key)) {
 | 
	
		
			
				|  |  | +      return instruments[key];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return '';
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * 乐器排序
 | 
	
		
			
				|  |  | + * 排序顺序:长笛、单簧管、中音单簧管、低音单簧管、高音萨克斯风、中音萨克斯风、次中音萨克斯风、低音萨克斯风、小号、长号、圆号、大号、上低音号
 | 
	
		
			
				|  |  | + * */
 | 
	
		
			
				|  |  | +export const sortMusical = (name: string, index: number) => {
 | 
	
		
			
				|  |  | +  let sortId = 0;
 | 
	
		
			
				|  |  | +  switch (name) {
 | 
	
		
			
				|  |  | +    case '长笛':
 | 
	
		
			
				|  |  | +      sortId = 1;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '单簧管':
 | 
	
		
			
				|  |  | +      sortId = 2;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '中音单簧管':
 | 
	
		
			
				|  |  | +      sortId = 3;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '低音单簧管':
 | 
	
		
			
				|  |  | +      sortId = 4;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '高音萨克斯风':
 | 
	
		
			
				|  |  | +      sortId = 5;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '中音萨克斯风':
 | 
	
		
			
				|  |  | +      sortId = 6;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '次中音萨克斯风':
 | 
	
		
			
				|  |  | +      sortId = 7;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '低音萨克斯风':
 | 
	
		
			
				|  |  | +      sortId = 8;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '小号':
 | 
	
		
			
				|  |  | +      sortId = 9;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '长号':
 | 
	
		
			
				|  |  | +      sortId = 10;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '圆号':
 | 
	
		
			
				|  |  | +      sortId = 11;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '大号':
 | 
	
		
			
				|  |  | +      sortId = 12;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    case '上低音号':
 | 
	
		
			
				|  |  | +      sortId = 13;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +    default:
 | 
	
		
			
				|  |  | +      sortId = index + 14;
 | 
	
		
			
				|  |  | +      break;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return sortId;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// 课堂乐器声轨名称集合
 | 
	
		
			
				|  |  | +const trackNames: any = {
 | 
	
		
			
				|  |  | +  Piccolo: 'Tenor Recorder',
 | 
	
		
			
				|  |  | +  flute: 'Flute',
 | 
	
		
			
				|  |  | +  Flute: 'Flute',
 | 
	
		
			
				|  |  | +  'Flute 1': 'Flute',
 | 
	
		
			
				|  |  | +  'Flute 2': 'Flute',
 | 
	
		
			
				|  |  | +  Oboe: 'Clarinet',
 | 
	
		
			
				|  |  | +  oboe: 'Clarinet',
 | 
	
		
			
				|  |  | +  clarinet: 'Clarinet',
 | 
	
		
			
				|  |  | +  'Clarinet in Bb': 'Clarinet',
 | 
	
		
			
				|  |  | +  'Clarinet in Bb 1': 'Clarinet',
 | 
	
		
			
				|  |  | +  'Clarinet in Bb 2': 'Clarinet',
 | 
	
		
			
				|  |  | +  'Alto Clarinet in Eb': 'Clarinet',
 | 
	
		
			
				|  |  | +  'Bass Clarinet in Bb': 'Clarinet',
 | 
	
		
			
				|  |  | +  Bassoon: 'Bassoon',
 | 
	
		
			
				|  |  | +  'Alto Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  'Tenor Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  'Baritone Saxophone': 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  altosaxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  tenorsaxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  saxophone: 'Alto Saxophone',
 | 
	
		
			
				|  |  | +  'Trumpet in Bb 1': 'Trumpet',
 | 
	
		
			
				|  |  | +  'Trumpet in Bb 2': 'Trumpet',
 | 
	
		
			
				|  |  | +  trumpet: 'Trumpet',
 | 
	
		
			
				|  |  | +  'Horn in F': 'Horn',
 | 
	
		
			
				|  |  | +  'Horn in F 1': 'Horn',
 | 
	
		
			
				|  |  | +  'Horn in F 2': 'Horn',
 | 
	
		
			
				|  |  | +  horn: 'Horn',
 | 
	
		
			
				|  |  | +  trombone: 'Trombone',
 | 
	
		
			
				|  |  | +  'Trombone 1': 'Trombone',
 | 
	
		
			
				|  |  | +  'Trombone 2': 'Trombone',
 | 
	
		
			
				|  |  | +  'Trombone 3': 'Trombone',
 | 
	
		
			
				|  |  | +  Euphonium: 'Baritone',
 | 
	
		
			
				|  |  | +  upbasshorn: 'Baritone',
 | 
	
		
			
				|  |  | +  Tuba: 'Tuba',
 | 
	
		
			
				|  |  | +  tuba: 'Tuba',
 | 
	
		
			
				|  |  | +  Chimes: 'Chimes',
 | 
	
		
			
				|  |  | +  Bells: 'Bells',
 | 
	
		
			
				|  |  | +  Xylophone: 'Xylophone',
 | 
	
		
			
				|  |  | +  'Snare Drum': 'Snare Drum',
 | 
	
		
			
				|  |  | +  'Bass Drum': 'Bass Drum',
 | 
	
		
			
				|  |  | +  Triangle: 'Triangle',
 | 
	
		
			
				|  |  | +  'Suspended Cymbal': 'Suspended Cymbal',
 | 
	
		
			
				|  |  | +  'Crash Cymbals': 'Crash Cymbals',
 | 
	
		
			
				|  |  | +  'Concert Toms': 'Concert Toms',
 | 
	
		
			
				|  |  | +  Timpani: 'Timpani',
 | 
	
		
			
				|  |  | +  'Drum Set': 'Drum Set',
 | 
	
		
			
				|  |  | +  Marimba: 'Marimba',
 | 
	
		
			
				|  |  | +  Vibraphone: 'Vibraphone',
 | 
	
		
			
				|  |  | +  'Tubular Bells': 'Tubular Bells',
 | 
	
		
			
				|  |  | +  Mallets: 'Mallets',
 | 
	
		
			
				|  |  | +  recorder: 'Piccolo',
 | 
	
		
			
				|  |  | +  tenorrecorder: 'piccolo',
 | 
	
		
			
				|  |  | +  melodica: 'melodica',
 | 
	
		
			
				|  |  | +  hulusiFlute: 'hulusiFlute',
 | 
	
		
			
				|  |  | +  panflute: 'panflute',
 | 
	
		
			
				|  |  | +  ukulele: 'ukulele',
 | 
	
		
			
				|  |  | +  mouthorgan: 'mouthorgan',
 | 
	
		
			
				|  |  | +  piano: 'piano',
 | 
	
		
			
				|  |  | +  woodwind: 'Woodwind',
 | 
	
		
			
				|  |  | +  panpipes: 'Panpipes',
 | 
	
		
			
				|  |  | +  ocarina: 'Ocarina',
 | 
	
		
			
				|  |  | +  nai: 'Nai',
 | 
	
		
			
				|  |  | +  BaroqueRecorder: 'Baroque Recorder'
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/** 声轨track转换成乐器code */
 | 
	
		
			
				|  |  | +export const trackToCode = (track: any) => {
 | 
	
		
			
				|  |  | +  return trackNames[track] || track;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +export const iframeDislableKeyboard = (iframeDom: any) => {
 | 
	
		
			
				|  |  | +  // 在 iframe 内部注入脚本禁用右键菜单
 | 
	
		
			
				|  |  | +  const script = document.createElement('script');
 | 
	
		
			
				|  |  | +  script.innerHTML = `
 | 
	
		
			
				|  |  | +      document.addEventListener('contextmenu', function(e) {
 | 
	
		
			
				|  |  | +          e.preventDefault();
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      document.addEventListener('keydown', function (event) {
 | 
	
		
			
				|  |  | +        // 屏蔽 F12 和 Ctrl+Shift+I
 | 
	
		
			
				|  |  | +        if (
 | 
	
		
			
				|  |  | +          event.key === 'F12' ||
 | 
	
		
			
				|  |  | +          (event.ctrlKey && event.shiftKey && event.key === 'I') ||
 | 
	
		
			
				|  |  | +          (event.metaKey && event.altKey && event.key === 'I')
 | 
	
		
			
				|  |  | +        ) {
 | 
	
		
			
				|  |  | +          event.preventDefault();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +            `;
 | 
	
		
			
				|  |  | +  if (iframeDom.contentWindow.document.body) {
 | 
	
		
			
				|  |  | +    iframeDom?.contentDocument?.body.appendChild(script);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 |