通用utils.ts

196 阅读1分钟
import { message } from 'antd';
import { OptsItemProps, FieldsProps } from '@/components/Adad/advForm';
import moment from 'moment';
import { getLs, setLs } from './common';

/* eslint no-useless-escape:0 import/prefer-default-export:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;

const isUrl = (path: string): boolean => reg.test(path);

/**
 * 判断为空
 */
export const isEmpty = (value: any) =>
  value === null ||
  value === undefined ||
  value === '' ||
  value === {} ||
  value === [] ||
  value.length === 0;

/**
 * 判断不为空
 */
export const isNotEmpty = (value: any) => !isEmpty(value);

const isAntDesignPro = (): boolean => {
  if (ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') {
    return true;
  }
  return window.location.hostname === 'preview.pro.ant.design';
};

/**
 * 嵌套JSON数组转平级, nodeKey: 嵌套的需要转换字段名称
 */
export const setJsonArray = (data: any[], nodeKey: string = 'subMenu') => {
  let result: any[] = [];
  data.forEach(json => {
    if (json) {
      if (isNotEmpty(json[nodeKey])) {
        result = result.concat(setJsonArray(json[nodeKey]));
      }
      result.push(json);
    }
  });
  return result;
};

const findRootParentIds = (data: any[], levelParam: string) => {
  const rootParentIds: string[] = [];
  let minLevel: number = -1;
  let isFirst = true;
  for (const item of data) {
    const levelData = parseInt(item[levelParam]);
    if (isNaN(levelData)) {
    } else if (isFirst) {
      minLevel = levelData;
      isFirst = false;
    } else if (minLevel > levelData) {
      minLevel = levelData;
    }
  }
  if (isNotEmpty(minLevel)) {
    const dataByMinLevel = data.filter(
      item => item[levelParam] && parseInt(item[levelParam]) === minLevel,
    );
    for (const dataItem of dataByMinLevel) {
      const { parentId } = dataItem;
      if (parentId && !rootParentIds.includes(parentId)) {
        rootParentIds.push(parentId);
      }
    }
  }
  return rootParentIds;
};

/**
 * 通用将平级JSON数组转嵌套
 * @param {*} data
 * @param {*} parentId
 * @param {*} subParam
 * @param {*} dataId
 */
export const setCommonJsonArrayNest = (
  data: any[],
  parentId: string = '0',
  subParam: string = 'subMenu',
  dataId: string = 'menuId',
): any[] => {
  const result: any[] = [];
  let temp;
  if (data) {
    data.forEach(json => {
      if (json.parentId === parentId) {
        temp = setCommonJsonArrayNest(data, json[dataId], subParam, dataId);
        if (isNotEmpty(temp)) {
          json[subParam] = temp;
        }
        result.push(json);
      }
    });
  }
  return result;
};

export const convertListToTreeJson = (
  data: any[],
  parentId: string = '0',
  subParam: string = 'subMenu',
  dataId: string = 'menuId',
  levelParam: string = 'menuLevel',
) => {
  const result = [];
  if (data) {
    const rootParentIds = findRootParentIds(data, levelParam);
    if (rootParentIds.length > 0) {
      for (const rootParentId of rootParentIds) {
        const tempResultArray = setCommonJsonArrayNest(data, rootParentId, subParam, dataId);
        for (const tempResult of tempResultArray) {
          result.push(tempResult);
        }
      }
    }
  }
  return result;
};

/**
 * 获取会话存储
 */
export const getSession = (key: string) => sessionStorage.getItem(key);

/**
 * 设置会话存储
 */
export const setSession = (key: string, value: string, check = false) => {
  if (check) {
    // 判断是否重复存在
    if (isEmpty(getSession(key))) {
      sessionStorage.setItem(key, value);
    }
  } else {
    sessionStorage.setItem(key, value);
  }
};

/**
 * 删除会话存储
 * @param key
 */
export const removeSession = (key: string) => sessionStorage.removeItem(key);

/**
 * 设置网站的Title
 * @param {*} title
 */
export const setDocumentTitle = (title: string) => {
  document.title = title;
};

/**
 * 设置页面的Title
 * @param sysName
 * @param sysVersion
 */
export const setAppTitle = (sysName: string, sysVersion: string) => {
  let title;
  const whitespace = ' ';
  if (sysName.includes('V') || sysName.includes('v')) {
    title = sysName;
  } else if (sysVersion.includes('V') || sysVersion.includes('v')) {
    title = `${sysName}${whitespace}${sysVersion}`;
  } else {
    title = `${sysName}${whitespace}v${sysVersion}`;
  }
  setDocumentTitle(title);
};

/**
 * 加载外部js资源
 */
export function loadScript(src: string) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;
    script.onload = resolve;
    script.onerror = reject;
    if (document.head) {
      document.head.appendChild(script);
    }
  });
}

/**
 * 设置页面的主题
 * @param obj
 * @param func
 * @param set
 */
let lessNodesAppended = false;
export const setThemes = (obj: object, func: Function, set: boolean = true) => {
  // Don't compile less in production!
  if (!obj) {
    return;
  }
  function buildIt() {
    if (!window.less) {
      return;
    }
    setTimeout(() => {
      window.less
        .modifyVars(obj)
        .then(() => {
          if (set) {
            message.destroy(); // 过快弹出多个
            message.success('预览主题成功.');
            if (func) {
              func();
            }
          }
        })
        .catch(() => {
          message.error('编译失败!');
        });
    }, 200);
  }
  if (!lessNodesAppended) {
    // insert less.js and color.less
    const lessStyleNode = document.createElement('link');
    const lessConfigNode = document.createElement('script');
    const lessScriptNode = document.createElement('script');
    lessStyleNode.setAttribute('rel', 'stylesheet/less');
    lessStyleNode.setAttribute('href', '/color.less');
    lessConfigNode.innerHTML = `
      window.less = {
        async: true,
        env: 'production',
        javascriptEnabled: true
      };
    `;
    lessScriptNode.src = 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js';
    lessScriptNode.async = true;
    lessScriptNode.onload = () => {
      buildIt();
      lessScriptNode.onload = null;
    };
    document.body.appendChild(lessStyleNode);
    document.body.appendChild(lessConfigNode);
    document.body.appendChild(lessScriptNode);
    lessNodesAppended = true;
  } else {
    buildIt();
  }
};

/**
 * 解析页面的主题
 * @param str
 * @return {any}
 */
export const parseThemes = (str: string) => {
  let obj = {};
  if (isNotEmpty(str)) {
    try {
      obj = JSON.parse(
        str
          .replace('@header', '@head-back-color')
          .replace('@sider', '@sider-back-color')
          .replace('@font', '@sider-select-color')
          .replace('@button', '@select-color')
          .replace('@table', '@table-header-color'),
      );
    } catch (e) { }
  }
  return obj;
};

export const getNodeHandle = (): ((json: any[], nodeId: string) => object) => {
  let parentNode: any[] = [];
  let node: any = null;
  const getNode = (json: any[], nodeId: string): object => {
    // 1.第一层 root 深度遍历整个JSON
    for (let i = 0; i < json.length; i++) {
      if (node) {
        break;
      }
      const obj = json[i];
      // 没有就下一个
      if (!obj || !obj.menuId) {
        continue;
      }
      // 2.有节点就开始找,一直递归下去
      if (obj.menuId === nodeId) {
        // 找到了与nodeId匹配的节点,结束递归
        node = obj;
        break;
      } else {
        // 3.如果有子节点就开始找
        if (obj.subMenu) {
          // 4.递归前,记录当前节点,作为parent 父亲
          parentNode.push(obj);
          // 递归往下找
          getNode(obj.subMenu, nodeId);
        }
        // else {
        //   // 跳出当前递归,返回上层递归
        //   continue;
        // }
      }
    }
    // 5.如果木有找到父节点,置为null,因为没有父亲
    if (!node) {
      parentNode = [];
    }
    let path = '';
    parentNode.map(item => {
      path += `${item.menuName}/`;
    });
    if (node) {
      path += `${node.menuName}`;
    }
    // 6.返回结果obj
    return {
      ...node,
      path,
    };
  };
  return getNode;
};

/**
 * 获取Pane包含的数据
 * @param {*} key 编号,一般对应Menu的Key
 * @param {*} title 标题,一般对应Menu的名称
 * @param {*} content 内容
 * @param {*} isWebDefault 是否网站首页
 * @param {string} path 路由地址
 * @param {*} url 菜单链接地址
 * @param {*} closable 是否可关闭
 * @param {*} isMenu 是否菜单页面
 * @param {*} refKey 来源Key值
 * @param {*} isExternal 是否为外部http|https地址
 */
export const getTabPaneData = ({
  key,
  title,
  content,
  path,
  isWebDefault = false,
  closable = false,
  isMenu = true,
  refKey = '',
  isExternal = false,
  url,
}: any) => {
  if (url) {
    return {
      paneKey: key,
      name: title,
      menuUrl: url,
      path: path || `/app/modules/${key}`,
      isWebDefault,
      closable,
      isMenu,
      refKey,
      isExternal,
    };
  }
  return {
    paneKey: key,
    name: title,
    content,
    path: path || `/app/${key}`,
    isWebDefault,
    closable,
    isMenu,
    refKey,
    isExternal,
  };
};

/**
 * 时间格式化
 * @param inputTime
 * @param fmt
 * @returns {*}
 */
export const dateFormat = (inputTime: string, fmt: string) => {
  if (!inputTime) return "";
  let date = new Date(inputTime);
  let o = {
    'M+': date.getMonth() + 1, //月份
    'd+': date.getDate(), //日
    'h+': date.getHours(), //小时
    'm+': date.getMinutes(), //分
    's+': date.getSeconds(), //秒
    'q+': Math.floor((date.getMonth() + 3) / 3), //季度
    S: date.getMilliseconds(), //毫秒
  };
  if (/(y+)/.test(fmt))
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  for (let k in o)
    if (new RegExp('(' + k + ')').test(fmt))
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length),
      );
  return fmt;
};

export declare interface RTreeDataItem {
  id?: string | number;
  treeId: string | number;
  key?: string | number;
  value?: string | number;
  title?: string;
  children?: Array<RTreeDataItem>;
}

export const rTreeDataFormat = (treeData: Array<RTreeDataItem>): Array<RTreeDataItem> => {
  return treeData.map(v => ({ ...v, value: v.treeId, key: v.treeId, children: rTreeDataFormat(v.children || []) }))
}

export const getNameById = (id: any, arr: Array<OptsItemProps>): string => {
  const filterArr = arr.filter(v => v.id == id);
  return filterArr.length > 0 ? filterArr[0].name : "";
}

export const initFieldsList = (fieldsList: FieldsProps[]): FieldsProps[] => {
  return fieldsList.map(v => {
    v.value = v.originValue;
    return v;
  })
}

export const bindFormValues = (record: any = {}, fieldsList: FieldsProps[]) => {
  return fieldsList.map(v => {
    if (v.editor === 'datePicker') {
      v.value = record[v.name] ? moment.utc(record[v.name]) : null;
    } else {
      v.value = record[v.name];
    }
    return v;
  });
}

declare interface treeItemProps {
  children?: Array<treeItemProps>
  [propName: string]: any;
}

export const treeToList = (treeData: treeItemProps[], resultData: treeItemProps[] = []) => {
  treeData.map(v => {
    resultData.push({
      ...v, children: undefined
    });
    if (v.children && v.children.length > 0) {
      treeToList(v.children, resultData)
    }
  });
  return resultData;
}

export const getObjectById = (id = "", treeData: treeItemProps[]) => {
  const filterArr = treeToList(treeData).filter(v => v.id === id);
  if (filterArr.length > 0) {
    return filterArr[0]
  } else {
    return {}
  }
}

export const activeMenuItem = (record: any = {}) => {
  const currentActiveMenu = getLs("currentActiveMenu", true) || [];
  const _currentActiveMenu = currentActiveMenu.filter((v: any) => v.url !== record.url);
  const resultArr: Array<any> = [record];
  _currentActiveMenu.map((item: any, index: number) => {
    if (_currentActiveMenu.length - 9 <= index) resultArr.push(item)
  })
  setLs("currentActiveMenu", [...resultArr], true);
}


export { isAntDesignPro, isUrl };