util.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // 获取客户端操作系统信息
  2. export const getUserOsInfo = function () {
  3. const userAgent = navigator.userAgent;
  4. if (userAgent.indexOf("Windows NT 10.0") !== -1) return "Windows 10";
  5. if (userAgent.indexOf("Windows NT 6.2") !== -1) return "Windows 8";
  6. if (userAgent.indexOf("Windows NT 6.1") !== -1) return "Windows 7";
  7. if (userAgent.indexOf("Windows NT 6.0") !== -1) return "Windows Vista";
  8. if (userAgent.indexOf("Windows NT 5.1") !== -1) return "Windows XP";
  9. if (userAgent.indexOf("Windows NT 5.0") !== -1) return "Windows 2000";
  10. if (userAgent.indexOf("Mac") !== -1) return "Mac/iOS";
  11. if (userAgent.indexOf("X11") !== -1) return "UNIX";
  12. if (userAgent.indexOf("Linux") !== -1) return "Linux";
  13. return "Other";
  14. }
  15. // 获取浏览器类型
  16. export const _mime = function (option, value) {
  17. var mimeTypes = navigator.mimeTypes;
  18. for (var mt in mimeTypes) {
  19. if (mimeTypes[mt][option] == value) {
  20. return true;
  21. }
  22. }
  23. return false;
  24. }
  25. export const getBrowserType = function () {
  26. let ua = navigator.userAgent.toLocaleLowerCase()
  27. let browserType = null
  28. if (ua.match(/msie/) != null || ua.match(/trident/) != null) {
  29. browserType = 'IE'
  30. } else if (ua.match(/firefox/) != null) {
  31. browserType = 'firefox'
  32. } else if (ua.match(/ucbrowser/) != null) {
  33. browserType = 'UC'
  34. } else if (ua.match(/opera/) != null || ua.match(/opr/) != null) {
  35. browserType = 'opera'
  36. } else if (ua.match(/bidubrowser/) != null) {
  37. browserType = 'baidu'
  38. } else if (ua.match(/metasr/) != null) {
  39. browserType = 'sougou'
  40. } else if (ua.match(/tencenttraveler/) != null || ua.match(/qqbrowse/) != null) {
  41. browserType = 'QQ'
  42. } else if (ua.match(/maxthon/) != null) {
  43. browserType = 'maxthon'
  44. } else if (ua.match(/chrome/) != null) {
  45. var is360 = _mime('type', 'application/vnd.chromium.remoting-viewer')
  46. if (is360) {
  47. browserType = '360'
  48. } else {
  49. browserType = 'chrome'
  50. }
  51. } else if (ua.match(/safari/) != null) {
  52. browserType = 'Safari'
  53. } else {
  54. browserType = 'others'
  55. }
  56. return browserType
  57. }
  58. export function timeFix () {
  59. const time = new Date()
  60. const hour = time.getHours()
  61. return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
  62. }
  63. export function welcome () {
  64. const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
  65. const index = Math.floor(Math.random() * arr.length)
  66. return arr[index]
  67. }
  68. /**
  69. * 触发 window.resize
  70. */
  71. export function triggerWindowResizeEvent () {
  72. const event = document.createEvent('HTMLEvents')
  73. event.initEvent('resize', true, true)
  74. event.eventType = 'message'
  75. window.dispatchEvent(event)
  76. }
  77. export function handleScrollHeader (callback) {
  78. let timer = 0
  79. let beforeScrollTop = window.pageYOffset
  80. callback = callback || function () {}
  81. window.addEventListener(
  82. 'scroll',
  83. event => {
  84. clearTimeout(timer)
  85. timer = setTimeout(() => {
  86. let direction = 'up'
  87. const afterScrollTop = window.pageYOffset
  88. const delta = afterScrollTop - beforeScrollTop
  89. if (delta === 0) {
  90. return false
  91. }
  92. direction = delta > 0 ? 'down' : 'up'
  93. callback(direction)
  94. beforeScrollTop = afterScrollTop
  95. }, 50)
  96. },
  97. false
  98. )
  99. }
  100. /**
  101. * 数组转树形结构
  102. * @param {array} list 被转换的数组
  103. * @param {number|string} root 根节点(最外层节点)的 id
  104. * @return array
  105. */
  106. export function arrayToTree (list, root) {
  107. const result = [] // 用于存放结果
  108. const map = {} // 用于存放 list 下的节点
  109. // 1. 遍历 list,将 list 下的所有节点以 id 作为索引存入 map
  110. for (const item of list) {
  111. map[item.id] = { ...item } // 浅拷贝
  112. }
  113. // 2. 再次遍历,将根节点放入最外层,子节点放入父节点
  114. for (const item of list) {
  115. // 3. 获取节点的 id 和 父 id
  116. const { id, parentId } = item // ES6 解构赋值
  117. // 4. 如果是根节点,存入 result
  118. if (item.parentId == root) {
  119. result.push(map[id])
  120. } else {
  121. // 5. 反之,存入到父节点
  122. map[parentId].children
  123. ? map[parentId].children.push(map[id])
  124. : (map[parentId].children = [map[id]])
  125. }
  126. }
  127. // 将结果返回
  128. return result
  129. }
  130. /**
  131. * Remove loading animate
  132. * @param id parent element id or class
  133. * @param timeout
  134. */
  135. export function removeLoadingAnimate (id = '', timeout = 1500) {
  136. if (id === '') {
  137. return
  138. }
  139. setTimeout(() => {
  140. document.body.removeChild(document.getElementById(id))
  141. }, timeout)
  142. }
  143. /**
  144. * @param {String|Number} value 要验证的字符串或数值
  145. * @param {*} validList 用来验证的列表
  146. */
  147. export function oneOf (value, validList) {
  148. for (let i = 0; i < validList.length; i++) {
  149. if (value === validList[i]) {
  150. return true
  151. }
  152. }
  153. return false
  154. }
  155. // 选择文本
  156. export function onTextSelected ($copyText, $message) {
  157. const textDiv = document.getElementsByClassName('copy-rect')
  158. const selection = window.getSelection()
  159. if (!selection) {
  160. return
  161. }
  162. if (selection.rangeCount <= 0) {
  163. return
  164. }
  165. const range = selection.getRangeAt(0)
  166. if (!range) {
  167. return
  168. }
  169. const rect = range.getBoundingClientRect()
  170. if (!rect) {
  171. return
  172. }
  173. if (rect.width <= 0) {
  174. return
  175. }
  176. const wholeText = range.startContainer.wholeText
  177. if (!wholeText) {
  178. return
  179. }
  180. if (wholeText && wholeText.length <= 0) {
  181. return
  182. }
  183. const str = wholeText.slice(range.startOffset, range.endOffset)
  184. if (!str) {
  185. return
  186. }
  187. let copyNode = textDiv[0]
  188. if (!copyNode) {
  189. if (str.length > 0) {
  190. copyNode = document.createElement('div')
  191. copyNode.innerHTML = '复制'
  192. copyNode.className = 'copy-rect'
  193. copyNode.style.position = 'fixed'
  194. copyNode.style.top = rect.top - rect.height - 10 + 'px'
  195. copyNode.style.left = rect.left + rect.width - 20 + 'px'
  196. copyNode.style.height = 'auto'
  197. copyNode.style.width = 'auto'
  198. document.body.appendChild(copyNode)
  199. copyNode.addEventListener('mousedown', (event) => {
  200. console.log(event)
  201. event.stopPropagation()
  202. console.log(str)
  203. $copyText(str).then(message => {
  204. console.log('copy', message)
  205. $message.success('复制完毕')
  206. document.body.removeChild(copyNode)
  207. }).catch(err => {
  208. console.log('copy.err', err)
  209. $message.error('复制失败')
  210. document.body.removeChild(copyNode)
  211. })
  212. })
  213. }
  214. }
  215. }