utils.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. import { h } from 'vue'
  2. import { NIcon } from 'naive-ui'
  3. import screenfull from 'screenfull'
  4. import throttle from 'lodash/throttle'
  5. import Image_404 from '../assets/images/exception/image-404.png'
  6. import html2canvas from 'html2canvas'
  7. import { downloadByA } from './file'
  8. import { toString } from './type'
  9. import cloneDeep from 'lodash/cloneDeep'
  10. import { WinKeyboard } from '@/enums/editPageEnum'
  11. import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum'
  12. import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
  13. /**
  14. * * 判断是否是开发环境
  15. * @return { Boolean }
  16. */
  17. export const isDev = () => {
  18. return import.meta.env.DEV
  19. }
  20. /**
  21. * * 生成一个不重复的ID
  22. * @param { Number } randomLength
  23. */
  24. export const getUUID = (randomLength = 10) => {
  25. return Number(Math.random().toString().substring(2, randomLength) + Date.now()).toString(36)
  26. }
  27. /**
  28. * * render 图标
  29. * @param icon 图标
  30. * @param set 设置项
  31. */
  32. export const renderIcon = (icon: any, set = {}) => {
  33. return () => h(NIcon, set, { default: () => h(icon) })
  34. }
  35. /**
  36. * * render 语言
  37. * @param lang 语言标识
  38. * @param set 设置项
  39. * @param tag 要渲染成的标签
  40. */
  41. export const renderLang = (lang: string, set = {}, tag = 'span') => {
  42. return () => h(tag, set, { default: () => window['$t'](lang) })
  43. }
  44. /**
  45. * * 获取错误处理图片,默认 404 图
  46. * @returns url
  47. */
  48. export const requireErrorImg = () => {
  49. return Image_404
  50. }
  51. /**
  52. * * 全屏操作函数
  53. * @param isFullscreen
  54. * @param isEnabled
  55. * @returns
  56. */
  57. export const screenfullFn = (isFullscreen?: boolean, isEnabled?: boolean) => {
  58. // 是否是全屏
  59. if (isFullscreen) return screenfull.isFullscreen
  60. // 是否支持全屏
  61. if (isEnabled) return screenfull.isEnabled
  62. if (screenfull.isEnabled) {
  63. screenfull.toggle()
  64. return
  65. }
  66. // TODO lang
  67. window['$message'].warning('您的浏览器不支持全屏功能!')
  68. }
  69. /**
  70. * 修改元素位置
  71. * @param target 对象
  72. * @param x X轴
  73. * @param y Y轴
  74. */
  75. export const setComponentPosition = (
  76. target: CreateComponentType | CreateComponentGroupType,
  77. x?: number,
  78. y?: number
  79. ) => {
  80. x && (target.attr.x = x)
  81. y && (target.attr.y = y)
  82. }
  83. /**
  84. * * 设置元素属性
  85. * @param HTMLElement 元素
  86. * @param key 键名
  87. * @param value 键值
  88. */
  89. export const setDomAttribute = <K extends keyof CSSStyleDeclaration, V extends CSSStyleDeclaration[K]>(
  90. HTMLElement: HTMLElement,
  91. key: K,
  92. value: V
  93. ) => {
  94. if (HTMLElement) {
  95. HTMLElement.style[key] = value
  96. }
  97. }
  98. /**
  99. * * 判断是否是 mac
  100. * @returns boolean
  101. */
  102. export const isMac = () => {
  103. return /macintosh|mac os x/i.test(navigator.userAgent)
  104. }
  105. /**
  106. * * 挂载监听
  107. */
  108. // eslint-disable-next-line no-undef
  109. export const addEventListener = <K extends keyof WindowEventMap>(
  110. target: HTMLElement | Document,
  111. type: K,
  112. listener: any,
  113. delay?: number,
  114. // eslint-disable-next-line no-undef
  115. options?: boolean | AddEventListenerOptions | undefined
  116. ) => {
  117. if (!target) return
  118. target.addEventListener(
  119. type,
  120. throttle(listener, delay || 300, {
  121. leading: true,
  122. trailing: false
  123. }),
  124. options
  125. )
  126. }
  127. /**
  128. * * 卸载监听
  129. */
  130. // eslint-disable-next-line no-undef
  131. export const removeEventListener = <K extends keyof WindowEventMap>(
  132. target: HTMLElement | Document,
  133. type: K,
  134. listener: any
  135. ) => {
  136. if (!target) return
  137. target.removeEventListener(type, listener)
  138. }
  139. /**
  140. * * 截取画面为图片并下载
  141. * @param html 需要截取的 DOM
  142. */
  143. export const canvasCut = (html: HTMLElement | null, callback?: Function) => {
  144. if (!html) {
  145. window['$message'].error('导出失败!')
  146. if (callback) callback()
  147. return
  148. }
  149. html2canvas(html, {
  150. backgroundColor: null,
  151. allowTaint: true,
  152. useCORS: true
  153. }).then((canvas: HTMLCanvasElement) => {
  154. window['$message'].success('导出成功!')
  155. downloadByA(canvas.toDataURL(), undefined, 'png')
  156. if (callback) callback()
  157. })
  158. }
  159. /**
  160. * * 函数过滤器
  161. * @param data 数据值
  162. * @param res 返回顶级对象
  163. * @param funcStr 函数字符串
  164. * @param isToString 是否转为字符串
  165. * @param errorCallBack 错误回调函数
  166. * @param successCallBack 成功回调函数
  167. * @returns
  168. */
  169. export const newFunctionHandle = (
  170. data: any,
  171. res: any,
  172. funcStr?: string,
  173. isToString?: boolean,
  174. errorCallBack?: Function,
  175. successCallBack?: Function
  176. ) => {
  177. try {
  178. if (!funcStr) return data
  179. const fn = new Function('data', 'res', funcStr)
  180. const fnRes = fn(cloneDeep(data), cloneDeep(res))
  181. const resHandle = isToString ? toString(fnRes) : fnRes
  182. // 成功回调
  183. successCallBack && successCallBack(resHandle)
  184. return resHandle
  185. } catch (error) {
  186. // 失败回调
  187. errorCallBack && errorCallBack(error)
  188. return '函数执行错误'
  189. }
  190. }
  191. /**
  192. * * 处理请求事件单位
  193. * @param num 时间间隔
  194. * @param unit RequestHttpIntervalEnum
  195. * @return number 秒数
  196. */
  197. export const intervalUnitHandle = (num: number, unit: RequestHttpIntervalEnum) => {
  198. switch (unit) {
  199. // 秒
  200. case RequestHttpIntervalEnum.SECOND:
  201. return num * 1000
  202. // 分
  203. case RequestHttpIntervalEnum.MINUTE:
  204. return num * 1000 * 60
  205. // 时
  206. case RequestHttpIntervalEnum.HOUR:
  207. return num * 1000 * 60 * 60
  208. // 天
  209. case RequestHttpIntervalEnum.DAY:
  210. return num * 1000 * 60 * 60 * 24
  211. default:
  212. return num * 1000
  213. }
  214. }
  215. /**
  216. * * 对象转换 cookie 格式
  217. * @param obj
  218. * @returns string
  219. */
  220. export const objToCookie = (obj: RequestParamsObjType) => {
  221. if (!obj) return ''
  222. let str = ''
  223. for (const key in obj) {
  224. str += key + '=' + obj[key] + ';'
  225. }
  226. return str.substring(0, str.length - 1)
  227. }
  228. /**
  229. * * 设置按下键盘按键的底部展示
  230. * @param keyCode
  231. * @returns
  232. */
  233. export const setKeyboardDressShow = (keyCode?: number) => {
  234. const code = new Map([
  235. [17, WinKeyboard.CTRL],
  236. [32, WinKeyboard.SPACE]
  237. ])
  238. const dom = document.getElementById('keyboard-dress-show')
  239. if (!dom) return
  240. if (!keyCode) {
  241. window.onKeySpacePressHold?.(false)
  242. dom.innerText = ''
  243. return
  244. }
  245. if (keyCode && code.has(keyCode)) {
  246. if (keyCode == 32) window.onKeySpacePressHold?.(true)
  247. dom.innerText = `按下了「${code.get(keyCode)}」键`
  248. }
  249. }
  250. /**
  251. * * JSON序列化,支持函数和 undefined
  252. * @param data
  253. */
  254. export const JSONStringify = (data: object) => {
  255. return JSON.stringify(
  256. data,
  257. (key, val) => {
  258. // 处理函数丢失问题
  259. if (typeof val === 'function') {
  260. return `${val}`
  261. }
  262. // 处理 undefined 丢失问题
  263. if (typeof val === 'undefined') {
  264. return 'undefined'
  265. }
  266. return val
  267. },
  268. 2
  269. )
  270. }
  271. /**
  272. * * JSON反序列化,支持函数和 undefined
  273. * @param data
  274. */
  275. export const JSONParse = (data: string) => {
  276. return JSON.parse(data, (k, v) => {
  277. if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) {
  278. return eval(`(function(){return ${v}})()`)
  279. }
  280. return v
  281. })
  282. }
  283. /**
  284. * * 修改顶部标题
  285. * @param title
  286. */
  287. export const setTitle = (title?: string) => {
  288. title && (document.title = title)
  289. }