工具函数tls

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

当前为 2023-06-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 工具函数tls
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.3
  5. // @description 挂载到window下一级属性集合-常用工具函数
  6. // @author Enjoy_li
  7. // @match *://*/*
  8. // @homepage https://greasyfork.org/zh-CN/scripts/468302-%E5%B7%A5%E5%85%B7%E5%87%BD%E6%95%B0tls
  9. // @license MIT
  10. // @icon https://foruda.gitee.com/avatar/1671100286067517749/4867929_enjoy_li_1671100285.png!avatar60
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. ; (function (win) {
  15.  
  16. getLogObjectValue(['v$0','vtemp1'])
  17.  
  18. const tools = {
  19. backPrototype,
  20. createPlainFile,
  21. getRegMobile,
  22. phoneFormat,
  23. getRegName,
  24. getRegEmail,
  25. getRegIDCard,
  26. getQuery,
  27. toSearch,
  28. transformThousandth,
  29. deleteProperty,
  30. asyncRequire,
  31. transformData,
  32. previewFile,
  33. dateUtil,
  34. toWithOpener,
  35. downloadFile,
  36. base64ToBlob,
  37. base64ImgtoFile,
  38. isHasBtnPower,
  39. getBrowerEnv,
  40. formatReportDataToStr,
  41. copyStrToClipboard,
  42. getPropertiesOfObj,
  43. lgd,
  44. lgd0,
  45. lgdt1,
  46. getPrototypeOfObject,
  47. getLogObjectValue
  48. }
  49.  
  50. function getPrototypeOfObject(Obj) {
  51. /** @描述 对象原型链 */
  52.  
  53. let idx = 1
  54. let str = `参数原型链是:${Obj.name || '参数'}.__proto__ ▶️ `
  55.  
  56. next(Obj)
  57.  
  58. return str
  59.  
  60. /** @描述 递归 */
  61. function next(obj) {
  62. let ObjType = Object.toLocaleString.call(obj)
  63. let ObjFlag = ObjType.match(/^\[object ([a-zA-Z]+)\]/)?.[1] || typeof ObjType
  64. str = `${str}第 ${idx}级【${ObjFlag}】.__proto__ ▶️ `
  65. idx++
  66. if (obj.__proto__) {
  67. next(obj.__proto__)
  68. } else {
  69. str = `${str}第 ${idx}级【null】`
  70. }
  71.  
  72. }
  73. }
  74.  
  75. function lgdt1(...rest) {
  76. /** @描述 以对象形式打印 $0 */
  77. console.log(`temp1 ==%O`,temp1,...rest)
  78. }
  79.  
  80. function lgd(...args) {
  81. /** @描述 以对象形式打印 temp1 */
  82.  
  83. let [desc,...rest] = args
  84. if (rest.length && typeof desc === 'string') {
  85. return console.log(`${desc} %O`,...rest)
  86. }
  87. console.log(`%O`,...args)
  88. }
  89.  
  90. function lgd0(...rest) {
  91. /** @描述 以对象形式打印 $0 */
  92. console.log(`$0 ==%O`,$0,...rest)
  93. }
  94.  
  95. function backPrototype(resourceObj) {
  96. /**
  97. * @description 对象原型链:继承谁的属性和方法
  98. * @param {*} resourceObj
  99. * @returns {*} string
  100. */
  101.  
  102. let str = ''
  103.  
  104. next(resourceObj)
  105.  
  106. str = str + 'null'
  107.  
  108. console.log(`%c 该对象原型链是:`,'color:red',str)
  109. return str
  110.  
  111. function next(obj) {
  112. let ObjType = Object.toLocaleString.call(obj)
  113. let ObjFlag = ObjType.match(/^\[object ([a-zA-Z]+)\]/)?.[1] || '无'
  114. str = str + ObjFlag + ' + .__proto__ >> '
  115. if (obj.__proto__) {
  116. next(obj.__proto__)
  117. }
  118. }
  119. }
  120.  
  121.  
  122. function createPlainFile(content = { a: 'a' },name = 'name') {
  123. /**
  124. * @description 创建文本文件
  125. * @param {string} [content={ a: 'a' }]
  126. * @param {string} [name='name']
  127. */
  128.  
  129. // 下载保存json文件
  130. var eleLink = document.createElement("a");
  131. eleLink.download = name + '.json';
  132. // 字符内容转变成blob地址
  133. var data = JSON.stringify(content,undefined,4);
  134. var blob = new Blob([data],{ type: "text/json" });
  135. eleLink.href = URL.createObjectURL(blob);
  136. // 触发点击
  137. eleLink.click();
  138. // 然后移除
  139. }
  140.  
  141. function getRegMobile() {
  142. /** @描述 正则 - 手机号 */
  143. return /^1[2|3|4|5|6|7|8|9][\d]{9}$/
  144. }
  145.  
  146. function phoneFormat(phone = '') {
  147. /** @描述 格式化 - 手机号 */
  148. if (!phone || !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(phone)) return;
  149. phone = phone.replace(/\D/g,'').slice(0,11);
  150. phone = phone
  151. .replace(/^(\d{3})/,'$1 ')
  152. .replace(/(\d{4})/,'$1 ')
  153. .replace(/[\s]+$/,'')
  154. return phone;
  155. }
  156.  
  157. function getRegName() {
  158. /** @描述 正则 - 姓名 */
  159.  
  160. return /^[0-9|A-Za-z|\u4e00-\u9fa5|\s]+$/
  161. }
  162.  
  163.  
  164. function getRegEmail() {
  165. /** @描述 正则 - 邮箱 */
  166.  
  167. return /^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i
  168. }
  169.  
  170. function getRegIDCard() {
  171. /** @描述 正则 - 大陆身份证号码 */
  172. 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)$/
  173. }
  174.  
  175. function getQuery(search = window.location.search) {
  176. /** @描述 获取 url 参数 */
  177.  
  178. const query = {}
  179. search
  180. .substr(1)
  181. .split('&')
  182. .forEach((str) => {
  183. const strArr = str.split('=')
  184. const key = strArr[0]
  185.  
  186. if (!key) return
  187.  
  188. let val = decodeURIComponent(strArr[1])
  189. try {
  190. val = JSON.parse(val)
  191. } catch (err) { }
  192. query[key] = val
  193. })
  194. return query
  195. }
  196.  
  197. function toSearch(obj = {}) {
  198. /** @描述 转换成 url search */
  199. const arr = Object.keys(obj).map((key) => {
  200. let val = obj[key]
  201.  
  202. if (typeof val !== 'string') {
  203. try {
  204. val = JSON.stringify(val)
  205. } catch (err) {
  206. console.error(err)
  207. }
  208. }
  209.  
  210. return `${key}=${encodeURIComponent(val)}`
  211. })
  212. return '?' + arr.join('&')
  213. }
  214.  
  215.  
  216. function transformThousandth(value,fixed) {
  217. /**
  218. * 格式化金额 千分符
  219. * @param value
  220. * @param fixed
  221. */
  222.  
  223. const needFixed = fixed != null
  224. const num = Number(value)
  225. if (isNaN(num)) {
  226. return needFixed ? (0).toFixed(fixed) : '0'
  227. }
  228. // return (needFixed ? num.toFixed(fixed) : num.toString()).replace(/(\d{1,3})(?=(\d{3})+(?:$|\.))/g, '$1,')
  229. const str = needFixed ? num.toFixed(fixed) : num.toString()
  230. const arr = str.split('.')
  231.  
  232. let result = arr[0] ? arr[0].replace(/(?=(?!\b)(\d{3})+$)/g,',') : '0'
  233. if (arr[1] != null) {
  234. result += `.${arr[1]}`
  235. }
  236.  
  237. return result
  238. }
  239.  
  240.  
  241. function deleteProperty(obj = {},v = [undefined,null,'']) {
  242. /**
  243. * 删除指定值的属性
  244. * @param obj
  245. */
  246.  
  247. const res = {}
  248. const isArray = Array.isArray(v)
  249. for (const key in obj) {
  250. if (isArray) {
  251. if (!v.includes(obj[key])) res[key] = obj[key]
  252. } else {
  253. if (obj[key] !== v) res[key] = obj[key]
  254. }
  255. }
  256. return res
  257. }
  258.  
  259.  
  260. function asyncRequire(url,name,type) {
  261. /**
  262. * 通过插入标签以加载 js/css 文件
  263. * @param {String} url 需要载入的 js/css url
  264. * @param {String} name 文件载入后挂载到 window 下的变量名
  265. * @param {String} type 文件类型 默认取后缀名
  266. */
  267.  
  268. return new Promise((resolve,reject) => {
  269. const head =
  270. document.head || document.getElementsByTagName('head')[0] || document.body
  271. const filePath = url.split('?')[0]
  272. const ext = filePath.substring(filePath.lastIndexOf('.') + 1)
  273.  
  274. if (document.getElementById(`async-require-${name || 'unknown'}`)) {
  275. return resolve(name ? window[name] : 'loaded')
  276. }
  277.  
  278. let element
  279. if (ext == 'js' || type == 'js') {
  280. element = document.createElement('script')
  281. element.src = url
  282. element.onload = (e) => resolve(name ? window[name] : e)
  283. } else if (ext == 'css' || type == 'css') {
  284. element = document.createElement('link')
  285. element.rel = 'stylesheet'
  286. element.type = 'text/css'
  287. element.href = url
  288. element.onload = resolve
  289. } else {
  290. return console.warn('好像有点不对劲...请指定文件类型: js | css')
  291. }
  292.  
  293. element.id = `async-require-${name}`
  294. element.onerror = reject
  295. head.appendChild(element)
  296. })
  297. }
  298.  
  299.  
  300. function transformData(sourceData,relation) {
  301. /**
  302. * 返回数据
  303. * @param {Array} sourceData 原数组
  304. * @param {Array} 映射字段
  305. */
  306.  
  307. return sourceData.map((item) => {
  308. const [key,name] = relation
  309. return {
  310. label: item[name],
  311. value: item[key],
  312. }
  313. })
  314. }
  315.  
  316. function previewFile(fileUrl) {
  317. /**
  318. * 在线预览文件
  319. * @param {String} fileUrl 静态资源地址
  320. */
  321.  
  322. let link = document.createElement('a')
  323. link.href = fileUrl
  324. let ext = (link.pathname.split('.')[1] || '').toLowerCase()
  325.  
  326. const allowedExt = {
  327. bmp: 1,
  328. gif: 1,
  329. jpg: 1,
  330. jpeg: 1,
  331. png: 1,
  332. apng: 1,
  333. webp: 1,
  334. htm: 1,
  335. html: 1,
  336. pdf: 1,
  337. }
  338.  
  339. if (ext && allowedExt[ext]) {
  340. const url = `https://static.hrwork.com/tools/pdfviewer/index.html?file=${encodeURIComponent(
  341. fileUrl
  342. )}`
  343. if (window?.__ZPA_CRX) {
  344. return void dispatchEvent(new CustomEvent('$create_tab',{ detail: url }))
  345. }
  346. window.open(url)
  347. } else {
  348. alert(`不支持在线预览此类型(${ext ?? ''})文件`)
  349. }
  350. }
  351.  
  352.  
  353. function dateUtil(time = new Date()) {
  354. /**
  355. * 获取特定格式日期
  356. * date: 可以为日期字符串、日期对象,不传参数默认当前系统时间
  357. * format: 输出日期时间格式, 不传参数默认 YYYY-MM-DD HH:mm:ss 格式
  358. * 例:
  359. * dateUtil().format()
  360. * // 2022-06-16 11:56:02
  361. *
  362. * // 不传入日期,默认以当前日期,格式化为特定格式日期
  363. * dateUtil().format('YYYY年MM月DD日 (周W) HH时mm分ss秒')
  364. * // 2022年06月16日 (周四) 12时01分51秒
  365. *
  366. * // 传入指定日期(string | date),格式化为指定格式日期(string)
  367. * dateUtil('2015.7.12').format('YYYY年MM月DD日 HH时mm秒ss分 星期W')
  368. * // 2015年07月12日 00时00分00秒 星期三
  369. */
  370.  
  371. time = typeof time === 'string' ? time.replace(/-/g,'/') : time
  372. const date = isNaN(new Date(time)) ? time : new Date(time);
  373. return { date,format };
  374. function format(rule = 'YYYY-MM-DD HH:mm:ss') {
  375. const weeks = ['日','一','二','三','四','五','六']
  376. const padStart = (d) => (d + '').padStart(2,'0')
  377. const M = date.getMonth() + 1 + ''
  378. const D = date.getDate() + ''
  379. const H = date.getHours() + ''
  380. const m = date.getMinutes() + ''
  381. const s = date.getSeconds() + ''
  382. return rule
  383. .replace('YYYY',date.getFullYear())
  384. .replace('MM',padStart(M))
  385. .replace('M',M)
  386. .replace('DD',padStart(D))
  387. .replace('D',D)
  388. .replace('HH',padStart(H))
  389. .replace('H',H)
  390. .replace('mm',padStart(m))
  391. .replace('m',m)
  392. .replace('ss',padStart(s))
  393. .replace('s',s)
  394. .replace(/W/,weeks[date.getDay()])
  395. .replace(/w/,date.getDay())
  396. }
  397. }
  398.  
  399.  
  400. function toWithOpener(href,options = {}) {
  401. /**
  402. * 共享opener跳转
  403. * @param { Object } router 如:
  404. * @param { Object } options 如:
  405. */
  406.  
  407. const { target = '_blank',routes } = options
  408. const win = window.open(href,target)
  409. // 设置新打开页面的面包屑
  410. if (routes && Array.isArray(routes)) {
  411. const cloneRoutes = [...routes]
  412. cloneRoutes.shift()
  413. cloneRoutes[cloneRoutes.length - 1] = {
  414. ...cloneRoutes[cloneRoutes.length - 1],
  415. a: true,
  416. path: '/zhaopintong/' + location.hash,
  417. }
  418. win.sessionStorage.parent_routes = JSON.stringify(cloneRoutes)
  419. }
  420. return win
  421. }
  422.  
  423.  
  424. function downloadFile(href,fileName = '') {
  425. /**
  426. * 通过url一键下载图片
  427. * @param { String } href 如:
  428. * @param { String } fileName 如:
  429. */
  430.  
  431. if (!href) {
  432. return
  433. }
  434. let aLink = document.createElement('a')
  435. aLink.download = fileName + Date.now()
  436. aLink.href = href
  437. aLink.click()
  438. }
  439.  
  440. function base64ToBlob(base64Code) {
  441. /**
  442. * base64转Blob对象
  443. * @param { String } code 如:
  444. */
  445.  
  446. const parts = base64Code.split(';base64,')
  447. const contentType = parts[0].split(':')[1]
  448. const raw = window.atob(parts[1])
  449. const rawLength = raw.length
  450. const uint8Array = new Uint8Array(rawLength)
  451. for (var i = 0; i < rawLength; i++) {
  452. uint8Array[i] = raw.charCodeAt(i)
  453. }
  454. return new Blob([uint8Array],{ type: contentType })
  455. }
  456.  
  457.  
  458. function base64ImgtoFile(base64Code,filename = 'file') {
  459. /**
  460. * base64转文件对象
  461. * @param { String } base64Code 如:
  462. * @param { String } filename 如:
  463. */
  464.  
  465. let arr = base64Code.split(',')
  466. let mime = arr[0].match(/:(.*?);/)[1]
  467. let suffix = mime.split('/')[1]
  468. let bstr = atob(arr[1])
  469. let n = bstr.length
  470. let u8arr = new Uint8Array(n)
  471. while (n--) {
  472. u8arr[n] = bstr.charCodeAt(n)
  473. }
  474. return new File([u8arr],`${filename}.${suffix}`,{
  475. type: mime,
  476. })
  477. }
  478.  
  479.  
  480. function isHasBtnPower(powerList = [],code = '') {
  481. /**
  482. * @description 判断角色是否有页面级按钮的权限
  483. * @param {*} [powerList=[]]
  484. * @param {string} [code='']
  485. * @returns {*} {boolean}
  486. */
  487.  
  488. if (!code) return false
  489.  
  490. if (typeof code === 'string') code = [code]
  491.  
  492. for (const value of code) {
  493. if (powerList?.includes?.(value)) return true
  494. }
  495. return false
  496. }
  497.  
  498.  
  499.  
  500. function getBrowerEnv() {
  501. /** @描述 判断当前浏览器运行环境 */
  502.  
  503. const userAgent = window.navigator.userAgent.toLowerCase()
  504. const agents = ["Android","iPhone","SymbianOS","Windows Phone","iPad","iPod"]
  505. // 是否为支付宝环境
  506. const isAliPay = /alipayclient/.test(userAgent)
  507. // 是否为淘宝环境
  508. const isTaoBao = /windvane/.test(userAgent)
  509. // 是否为企业微信环境
  510. const isWxWork = /wxwork/.test(userAgent)
  511. // 是否为微信环境
  512. const isWeChat = /micromessenger/.test(userAgent) && !isWxWork
  513. // 是否为移动端
  514. const isPhone = agents.some(x => new RegExp(x.toLocaleLowerCase()).test(userAgent))
  515. return { isAliPay,isTaoBao,isWxWork,isWeChat,isPhone }
  516. }
  517.  
  518.  
  519. //
  520. function formatReportDataToStr(arr = [],headerLabel = []) {
  521. /** @描述 格式化报表数据拼接成字符串,以便复制到剪贴板 */
  522.  
  523. return arr.reduce(
  524. (pre,cur) => {
  525. return (
  526. pre +
  527. headerLabel.reduceRight((pre2,cur2) => {
  528. return `${cur[cur2.key]}\t${pre2}`
  529. },'\n')
  530. )
  531. },
  532. headerLabel.reduceRight((pre,cur) => {
  533. return `${cur.title}\t${pre}`
  534. },'\n')
  535. )
  536. }
  537.  
  538.  
  539. function copyStrToClipboard(value) {
  540. /** @描述 把字符串复制到剪贴板 */
  541.  
  542. const textarea = document.createElement('textarea')
  543. textarea.value = value
  544. document.body.appendChild(textarea)
  545. textarea.select()
  546. document.execCommand('Copy')
  547. document.body.removeChild(textarea)
  548. }
  549.  
  550. async function copyStrToClipboardOfNavigator(value) {
  551. /** @描述 把字符串复制到剪贴板 */
  552.  
  553. return await navigator.clipboard.writeText(value)
  554. }
  555.  
  556.  
  557. function getPropertiesOfObj({ obj = {},keys = [] }) {
  558. /**
  559. * @描述 获取对象的指定属性集合
  560. * @param {*} { obj = {}, keys = [] }
  561. * @returns {*}
  562. */
  563.  
  564. let newObj = {}
  565. keys.forEach((key) => {
  566. newObj[key] = obj[key]
  567. })
  568. return newObj
  569. }
  570.  
  571.  
  572. function getLogObjectValue(arr,win = window) {
  573. /** @描述 定义以对象形式 获取window属性值 */
  574. arr.forEach((newKey) => {
  575. Object.defineProperty(win,newKey,{
  576. get() {
  577. return win[newKey.slice(1)]
  578. }
  579. })
  580. })
  581. }
  582.  
  583.  
  584.  
  585. if (win.tl) {
  586. console.error('win.tl已经存在,请使用win.tls')
  587. if (!win.tls) win.tls = tools
  588. return
  589. }
  590. win.tl = tools
  591. Object.defineProperty(tools,'fns',{
  592. /** @描述 对象下的函数名列表 */
  593. get() {
  594. return Object.keys(tools)
  595. }
  596. })
  597. })(window)