util.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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. * Remove loading animate
  102. * @param id parent element id or class
  103. * @param timeout
  104. */
  105. export function removeLoadingAnimate (id = '', timeout = 1500) {
  106. if (id === '') {
  107. return
  108. }
  109. setTimeout(() => {
  110. document.body.removeChild(document.getElementById(id))
  111. }, timeout)
  112. }
  113. /**
  114. * @param {String|Number} value 要验证的字符串或数值
  115. * @param {*} validList 用来验证的列表
  116. */
  117. export function oneOf (value, validList) {
  118. for (let i = 0; i < validList.length; i++) {
  119. if (value === validList[i]) {
  120. return true
  121. }
  122. }
  123. return false
  124. }
  125. /**
  126. * @param {Function} fn 防抖函数
  127. * @param {Number} delay 延迟时间
  128. */
  129. export function debounce(fn, delay) {
  130. var timer;
  131. return function () {
  132. var context = this;
  133. var args = arguments;
  134. clearTimeout(timer);
  135. timer = setTimeout(function () {
  136. fn.apply(context, args);
  137. }, delay);
  138. };
  139. }
  140. /**
  141. * @param {date} time 需要转换的时间
  142. * @param {String} fmt 需要转换的格式 如 yyyy-MM-dd、yyyy-MM-dd HH:mm:ss
  143. */
  144. export function formatTime(time, fmt) {
  145. if (!time) return '';
  146. else {
  147. const date = new Date(time);
  148. const o = {
  149. 'M+': date.getMonth() + 1,
  150. 'd+': date.getDate(),
  151. 'H+': date.getHours(),
  152. 'm+': date.getMinutes(),
  153. 's+': date.getSeconds(),
  154. 'q+': Math.floor((date.getMonth() + 3) / 3),
  155. S: date.getMilliseconds(),
  156. };
  157. if (/(y+)/.test(fmt))
  158. fmt = fmt.replace(
  159. RegExp.$1,
  160. (date.getFullYear() + '').substr(4 - RegExp.$1.length)
  161. );
  162. for (const k in o) {
  163. if (new RegExp('(' + k + ')').test(fmt)) {
  164. fmt = fmt.replace(
  165. RegExp.$1,
  166. RegExp.$1.length === 1
  167. ? o[k]
  168. : ('00' + o[k]).substr(('' + o[k]).length)
  169. );
  170. }
  171. }
  172. return fmt;
  173. }
  174. }
  175. // 千分位分隔符
  176. export function formatThousands (number) {
  177. if(!number){return 0}
  178. const arr = number.toString().split('.')
  179. const numbers = arr[0].split('').reverse()
  180. const segs = []
  181. while (numbers.length) segs.push(numbers.splice(0, 3).join(''))
  182. return segs.join(',').split('').reverse().join('') + (arr.length>1 ? ("."+arr[1]) : '')
  183. }
  184. /**
  185. * 数组转树形结构
  186. * @param {array} list 被转换的数组
  187. * @param {number|string} root 根节点(最外层节点)的 id
  188. * @return array
  189. */
  190. export function arrayToTree(list, root) {
  191. const result = [] // 用于存放结果
  192. const map = {} // 用于存放 list 下的节点
  193. // 1. 遍历 list,将 list 下的所有节点以 id 作为索引存入 map
  194. for (const item of list) {
  195. map[item.id] = { ...item } // 浅拷贝
  196. }
  197. // 2. 再次遍历,将根节点放入最外层,子节点放入父节点
  198. for (const item of list) {
  199. // 3. 获取节点的 id 和 父 id
  200. const { id, parentId } = item // ES6 解构赋值
  201. // 4. 如果是根节点,存入 result
  202. if (item.parentId == root) {
  203. result.push(map[id])
  204. } else {
  205. // 5. 反之,存入到父节点
  206. map[parentId].children
  207. ? map[parentId].children.push(map[id])
  208. : (map[parentId].children = [map[id]])
  209. }
  210. }
  211. // 将结果返回
  212. return result
  213. }
  214. // 树查找
  215. export function treeFind (tree, func) {
  216. for (const data of tree) {
  217. if (func(data)) return data
  218. if (data.children) {
  219. const res = treeFind(data.children, func)
  220. if (res) return res
  221. }
  222. }
  223. return null
  224. }
  225. // 是否有价格权限
  226. export function hasPriceAuth(authNode, priceOptions, userAuthCode){
  227. const codes = []
  228. const ret = []
  229. // 过滤当前节点下的非价格权限菜单
  230. authNode.map(item=>{
  231. const a = item.code.split('_')
  232. const hasCode = priceOptions.find(k => k.value == a[a.length-1])
  233. const hasRoles = userAuthCode.includes(item.code)
  234. // 获取当前用户的角色拥有的价格权限
  235. if(hasCode && hasRoles){
  236. codes.push(a[a.length-1])
  237. }
  238. })
  239. // console.log(codes)
  240. // 根据拥有的价格权限生成数组标记[1,0,1,0,0],每一位对应一个价格权限
  241. // 有权限标记1,否则标记0
  242. priceOptions.map(item => {
  243. ret.push(codes.includes(item.value)?1:0)
  244. })
  245. // console.log(ret)
  246. return ret
  247. }
  248. // 获取接口对应的价格权限code
  249. export function getAuthPriceCode (config, router, store) {
  250. // 通过路由打开的页面的权限code
  251. const permission = router.history.current.meta.permission
  252. // 手动指定的权限code,如打开的弹框页面或导出、打印
  253. // 手动指定的权限在使用完后需要清空,如在关闭弹框或导出、打印接口调用完成后清空
  254. const curActionPermission = store.state.app.curActionPermission
  255. // 价格权限的所有选项,销售价、成本价、省、市、特约价
  256. const priceOptions = store.state.app.priceAuthOptions
  257. // 最终获取的权限code,手动指定的优先级高于路由打开的页面权限code
  258. const authCode = curActionPermission || permission
  259. // 当前角色的分配的价格权限,这里过滤非价格权限code
  260. const roles = store.state.user.roles
  261. const userAuthCode = roles.permissionList.filter(item => {
  262. const a = item.split('_')
  263. return priceOptions.find(k => k.value == a[a.length-1])
  264. })
  265. // 如果有权限code
  266. if(authCode){
  267. // 当前正在调用的接口url
  268. const url = config.url
  269. // 所有的权限菜单数据
  270. const authTree = store.state.app.authMenusList
  271. // 从所有的权限菜单中查找当前权限code对应的权限菜单数据
  272. const authNode = treeFind(authTree,(item)=>item.code == authCode)
  273. console.log(authNode,url.replace(/\//g,'_'))
  274. if(!authNode){return []}
  275. if(!authNode.permission){return []}
  276. // 从找到的对应权限菜单数据中判断当前调用接口的url是否存在,这里和权限菜单中的后台权限code比较
  277. const hasReqUrl = authNode.permission.split(',').find(item => url.replace(/\//g,'_').indexOf(item)>=0)
  278. console.log(hasReqUrl)
  279. // 如果存在则返回一个如 [1,0,1,0,0] 的格式的价格权限字符串给后台接口
  280. if(hasReqUrl&&authNode.children&&authNode.children.length){
  281. return hasPriceAuth(authNode.children,priceOptions,userAuthCode)
  282. }
  283. return []
  284. }
  285. return []
  286. }