工具函数tls

挂载到window下一级属性集合-常用工具函数

目前為 2023-06-13 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         工具函数tls
// @namespace    http://tampermonkey.net/
// @version      0.1.2
// @description  挂载到window下一级属性集合-常用工具函数
// @author       Enjoy_li
// @match        *://*/*
// @homepage     
// @license MIT
// @icon         https://foruda.gitee.com/avatar/1671100286067517749/4867929_enjoy_li_1671100285.png!avatar60
// @grant        none
// ==/UserScript==

; (function (win) {
  const tools = {
    backPrototype,
    createPlainFile,
    getRegMobile,
    phoneFormat,
    getRegName,
    getRegEmail,
    getRegIDCard,
    getQuery,
    toSearch,
    transformThousandth,
    deleteProperty,
    asyncRequire,
    transformData,
    previewFile,
    dateUtil,
    toWithOpener,
    downloadFile,
    base64ToBlob,
    base64ImgtoFile,
    isHasBtnPower,
    getBrowerEnv,
    formatReportDataToStr,
    copyStrToClipboard,
    getPropertiesOfObj,
    lgd,
    lgd0,
    lgdt1,
    getPrototypeOfObject,
    getLogObjectValue
  }

  Object.defineProperty(tools,'fns',{
    /** @描述 对象下的函数名列表 */
    get(){
      return Object.keys(tools)
    }
  })

  function getLogObjectValue(arr,win = window) {
    /** @描述 定义以对象形式 获取window属性值 */
    arr.forEach((newKey) => {
      Object.defineProperty(win,newKey,{
        get() {
          return win[newKey.slice(1)]
        }
      })
    })
  }
  getLogObjectValue(['v$0','vtemp1'])

  function getPrototypeOfObject(Obj) {
    /** @描述 对象原型链 */

    let idx = 1
    let str = `参数原型链是:${Obj.name || '参数'}.__proto__ ▶️ `

    next(Obj)

    return str

    /** @描述 递归 */
    function next(obj) {
      let ObjType = Object.toLocaleString.call(obj)
      let ObjFlag = ObjType.match(/^\[object ([a-zA-Z]+)\]/)?.[1] || typeof ObjType
      str = `${str}第 ${idx}级【${ObjFlag}】.__proto__ ▶️ `
      idx++
      if (obj.__proto__) {
        next(obj.__proto__)
      } else {
        str = `${str}第 ${idx}级【null】`
      }

    }
  }

  function lgdt1(...rest) {
    /** @描述 以对象形式打印 $0 */
    console.log(`temp1 ==%O`,temp1,...rest)
  }

  function lgd(...args) {
    /** @描述 以对象形式打印 temp1 */

    let [desc,...rest] = args
    if (rest.length && typeof desc === 'string') {
      return console.log(`${desc} %O`,...rest)
    }
    console.log(`%O`,...args)
  }

  function lgd0(...rest) {
    /** @描述 以对象形式打印 $0 */
    console.log(`$0 ==%O`,$0,...rest)
  }

  function backPrototype(resourceObj) {
    /**
   * @description 对象原型链:继承谁的属性和方法
   * @param {*} resourceObj
   * @returns {*} string
   */

    let str = ''

    next(resourceObj)

    str = str + 'null'

    console.log(`%c 该对象原型链是:`,'color:red',str)
    return str

    function next(obj) {
      let ObjType = Object.toLocaleString.call(obj)
      let ObjFlag = ObjType.match(/^\[object ([a-zA-Z]+)\]/)?.[1] || '无'
      str = str + ObjFlag + ' + .__proto__ >> '
      if (obj.__proto__) {
        next(obj.__proto__)
      }
    }
  }


  function createPlainFile(content = { a: 'a' },name = 'name') {
    /**
   * @description 创建文本文件
   * @param {string} [content={ a: 'a' }]
   * @param {string} [name='name']
   */

    // 下载保存json文件
    var eleLink = document.createElement("a");
    eleLink.download = name + '.json';
    // 字符内容转变成blob地址
    var data = JSON.stringify(content,undefined,4);
    var blob = new Blob([data],{ type: "text/json" });
    eleLink.href = URL.createObjectURL(blob);
    // 触发点击
    eleLink.click();
    // 然后移除
  }

  function getRegMobile() {
    /** @描述 正则 - 手机号 */
    return /^1[2|3|4|5|6|7|8|9][\d]{9}$/
  }

  function phoneFormat(phone = '') {
    /** @描述 格式化 - 手机号 */
    if (!phone || !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(phone)) return;
    phone = phone.replace(/\D/g,'').slice(0,11);
    phone = phone
      .replace(/^(\d{3})/,'$1  ')
      .replace(/(\d{4})/,'$1  ')
      .replace(/[\s]+$/,'')
    return phone;
  }

  function getRegName() {
    /** @描述 正则 - 姓名 */

    return /^[0-9|A-Za-z|\u4e00-\u9fa5|\s]+$/
  }


  function getRegEmail() {
    /** @描述 正则 - 邮箱 */

    return /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i
  }

  function getRegIDCard() {
    /** @描述 正则 - 大陆身份证号码 */
    return /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
  }

  function getQuery(search = window.location.search) {
    /** @描述 获取 url 参数 */

    const query = {}
    search
      .substr(1)
      .split('&')
      .forEach((str) => {
        const strArr = str.split('=')
        const key = strArr[0]

        if (!key) return

        let val = decodeURIComponent(strArr[1])
        try {
          val = JSON.parse(val)
        } catch (err) { }
        query[key] = val
      })
    return query
  }

  function toSearch(obj = {}) {
    /** @描述 转换成 url search */
    const arr = Object.keys(obj).map((key) => {
      let val = obj[key]

      if (typeof val !== 'string') {
        try {
          val = JSON.stringify(val)
        } catch (err) {
          console.error(err)
        }
      }

      return `${key}=${encodeURIComponent(val)}`
    })
    return '?' + arr.join('&')
  }


  function transformThousandth(value,fixed) {
    /**
 * 格式化金额 千分符
 * @param value
 * @param fixed
 */

    const needFixed = fixed != null
    const num = Number(value)
    if (isNaN(num)) {
      return needFixed ? (0).toFixed(fixed) : '0'
    }
    // return (needFixed ? num.toFixed(fixed) : num.toString()).replace(/(\d{1,3})(?=(\d{3})+(?:$|\.))/g, '$1,')
    const str = needFixed ? num.toFixed(fixed) : num.toString()
    const arr = str.split('.')

    let result = arr[0] ? arr[0].replace(/(?=(?!\b)(\d{3})+$)/g,',') : '0'
    if (arr[1] != null) {
      result += `.${arr[1]}`
    }

    return result
  }


  function deleteProperty(obj = {},v = [undefined,null,'']) {
    /**
 * 删除指定值的属性
 * @param obj
 */

    const res = {}
    const isArray = Array.isArray(v)
    for (const key in obj) {
      if (isArray) {
        if (!v.includes(obj[key])) res[key] = obj[key]
      } else {
        if (obj[key] !== v) res[key] = obj[key]
      }
    }
    return res
  }


  function asyncRequire(url,name,type) {
    /**
 * 通过插入标签以加载 js/css 文件
 * @param {String} url 需要载入的 js/css url
 * @param {String} name 文件载入后挂载到 window 下的变量名
 * @param {String} type 文件类型 默认取后缀名
 */

    return new Promise((resolve,reject) => {
      const head =
        document.head || document.getElementsByTagName('head')[0] || document.body
      const filePath = url.split('?')[0]
      const ext = filePath.substring(filePath.lastIndexOf('.') + 1)

      if (document.getElementById(`async-require-${name || 'unknown'}`)) {
        return resolve(name ? window[name] : 'loaded')
      }

      let element
      if (ext == 'js' || type == 'js') {
        element = document.createElement('script')
        element.src = url
        element.onload = (e) => resolve(name ? window[name] : e)
      } else if (ext == 'css' || type == 'css') {
        element = document.createElement('link')
        element.rel = 'stylesheet'
        element.type = 'text/css'
        element.href = url
        element.onload = resolve
      } else {
        return console.warn('好像有点不对劲...请指定文件类型: js | css')
      }

      element.id = `async-require-${name}`
      element.onerror = reject
      head.appendChild(element)
    })
  }


  function transformData(sourceData,relation) {
    /**
 * 返回数据
 * @param {Array} sourceData 原数组
 * @param {Array} 映射字段
 */

    return sourceData.map((item) => {
      const [key,name] = relation
      return {
        label: item[name],
        value: item[key],
      }
    })
  }

  function previewFile(fileUrl) {
    /**
 * 在线预览文件
 * @param  {String}  fileUrl  静态资源地址
 */

    let link = document.createElement('a')
    link.href = fileUrl
    let ext = (link.pathname.split('.')[1] || '').toLowerCase()

    const allowedExt = {
      bmp: 1,
      gif: 1,
      jpg: 1,
      jpeg: 1,
      png: 1,
      apng: 1,
      webp: 1,
      htm: 1,
      html: 1,
      pdf: 1,
    }

    if (ext && allowedExt[ext]) {
      const url = `https://static.hrwork.com/tools/pdfviewer/index.html?file=${encodeURIComponent(
        fileUrl
      )}`
      if (window?.__ZPA_CRX) {
        return void dispatchEvent(new CustomEvent('$create_tab',{ detail: url }))
      }
      window.open(url)
    } else {
      alert(`不支持在线预览此类型(${ext ?? ''})文件`)
    }
  }


  function dateUtil(time = new Date()) {
    /**
 * 获取特定格式日期
 * date: 可以为日期字符串、日期对象,不传参数默认当前系统时间
 * format: 输出日期时间格式, 不传参数默认 YYYY-MM-DD HH:mm:ss 格式
 * 例:
 * dateUtil().format()
 * // 2022-06-16 11:56:02
 *
 * // 不传入日期,默认以当前日期,格式化为特定格式日期
 * dateUtil().format('YYYY年MM月DD日 (周W) HH时mm分ss秒')
 * // 2022年06月16日 (周四) 12时01分51秒
 *
 * // 传入指定日期(string | date),格式化为指定格式日期(string)
 * dateUtil('2015.7.12').format('YYYY年MM月DD日 HH时mm秒ss分 星期W')
 * // 2015年07月12日 00时00分00秒 星期三
 */

    time = typeof time === 'string' ? time.replace(/-/g,'/') : time
    const date = isNaN(new Date(time)) ? time : new Date(time);
    return { date,format };
    function format(rule = 'YYYY-MM-DD HH:mm:ss') {
      const weeks = ['日','一','二','三','四','五','六']
      const padStart = (d) => (d + '').padStart(2,'0')
      const M = date.getMonth() + 1 + ''
      const D = date.getDate() + ''
      const H = date.getHours() + ''
      const m = date.getMinutes() + ''
      const s = date.getSeconds() + ''
      return rule
        .replace('YYYY',date.getFullYear())
        .replace('MM',padStart(M))
        .replace('M',M)
        .replace('DD',padStart(D))
        .replace('D',D)
        .replace('HH',padStart(H))
        .replace('H',H)
        .replace('mm',padStart(m))
        .replace('m',m)
        .replace('ss',padStart(s))
        .replace('s',s)
        .replace(/W/,weeks[date.getDay()])
        .replace(/w/,date.getDay())
    }
  }


  function toWithOpener(href,options = {}) {
    /**
 * 共享opener跳转
 * @param { Object } router  如:
 * @param { Object } options  如:
 */

    const { target = '_blank',routes } = options
    const win = window.open(href,target)
    // 设置新打开页面的面包屑
    if (routes && Array.isArray(routes)) {
      const cloneRoutes = [...routes]
      cloneRoutes.shift()
      cloneRoutes[cloneRoutes.length - 1] = {
        ...cloneRoutes[cloneRoutes.length - 1],
        a: true,
        path: '/zhaopintong/' + location.hash,
      }
      win.sessionStorage.parent_routes = JSON.stringify(cloneRoutes)
    }
    return win
  }


  function downloadFile(href,fileName = '') {
    /**
 * 通过url一键下载图片
 * @param { String } href  如:
 * @param { String } fileName  如:
 */

    if (!href) {
      return
    }
    let aLink = document.createElement('a')
    aLink.download = fileName + Date.now()
    aLink.href = href
    aLink.click()
  }

  function base64ToBlob(base64Code) {
    /**
     * base64转Blob对象
     * @param { String } code  如:
     */

    const parts = base64Code.split(';base64,')
    const contentType = parts[0].split(':')[1]
    const raw = window.atob(parts[1])
    const rawLength = raw.length
    const uint8Array = new Uint8Array(rawLength)
    for (var i = 0; i < rawLength; i++) {
      uint8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uint8Array],{ type: contentType })
  }


  function base64ImgtoFile(base64Code,filename = 'file') {
    /**
 * base64转文件对象
 * @param { String } base64Code  如:
 * @param { String } filename  如:
 */

    let arr = base64Code.split(',')
    let mime = arr[0].match(/:(.*?);/)[1]
    let suffix = mime.split('/')[1]
    let bstr = atob(arr[1])
    let n = bstr.length
    let u8arr = new Uint8Array(n)
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr],`${filename}.${suffix}`,{
      type: mime,
    })
  }


  function isHasBtnPower(powerList = [],code = '') {
    /**
 * @description 判断角色是否有页面级按钮的权限
 * @param {*} [powerList=[]]
 * @param {string} [code='']
 * @returns {*}  {boolean}
 */

    if (!code) return false

    if (typeof code === 'string') code = [code]

    for (const value of code) {
      if (powerList?.includes?.(value)) return true
    }
    return false
  }



  function getBrowerEnv() {
    /** @描述 判断当前浏览器运行环境 */

    const userAgent = window.navigator.userAgent.toLowerCase()
    const agents = ["Android","iPhone","SymbianOS","Windows Phone","iPad","iPod"]
    // 是否为支付宝环境
    const isAliPay = /alipayclient/.test(userAgent)
    // 是否为淘宝环境
    const isTaoBao = /windvane/.test(userAgent)
    // 是否为企业微信环境
    const isWxWork = /wxwork/.test(userAgent)
    // 是否为微信环境
    const isWeChat = /micromessenger/.test(userAgent) && !isWxWork
    // 是否为移动端
    const isPhone = agents.some(x => new RegExp(x.toLocaleLowerCase()).test(userAgent))
    return { isAliPay,isTaoBao,isWxWork,isWeChat,isPhone }
  }


  // 
  function formatReportDataToStr(arr = [],headerLabel = []) {
    /** @描述 格式化报表数据拼接成字符串,以便复制到剪贴板 */

    return arr.reduce(
      (pre,cur) => {
        return (
          pre +
          headerLabel.reduceRight((pre2,cur2) => {
            return `${cur[cur2.key]}\t${pre2}`
          },'\n')
        )
      },
      headerLabel.reduceRight((pre,cur) => {
        return `${cur.title}\t${pre}`
      },'\n')
    )
  }


  function copyStrToClipboard(value) {
    /** @描述 把字符串复制到剪贴板 */

    const textarea = document.createElement('textarea')
    textarea.value = value
    document.body.appendChild(textarea)
    textarea.select()
    document.execCommand('Copy')
    document.body.removeChild(textarea)
  }

  async function copyStrToClipboardOfNavigator(value) {
    /** @描述 把字符串复制到剪贴板 */

    return await navigator.clipboard.writeText(value)
  }


  function getPropertiesOfObj({ obj = {},keys = [] }) {
    /**
 * @描述 获取对象的指定属性集合
 * @param {*} { obj = {}, keys = [] }
 * @returns {*}
 */

    let newObj = {}
    keys.forEach((key) => {
      newObj[key] = obj[key]
    })
    return newObj
  }

  if (win.tl) {
    console.error('win.tl已经存在,请使用win.tls')
    if (!win.tls) win.tls = tools
    return
  }
  win.tl = tools
})(window)