index.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. export * as sugar from './sugar'
  2. export * as router from './router'
  3. export * as h5Utils from './h5Utils'
  4. export * as appletUtils from './appletUtils'
  5. export * from './retryAsync'
  6. import pagesJson from '@/pages.json'
  7. export const isPromise = (obj) => {
  8. return !!obj && (typeof obj === "object" || typeof obj === "function") && typeof obj.then === "function";
  9. }
  10. let promisifyFlag = false
  11. export const promisify = () => {
  12. if (promisifyFlag) return
  13. promisifyFlag = true
  14. // #ifdef VUE2
  15. uni.addInterceptor({
  16. returnValue(res) {
  17. if (isPromise(res)) {
  18. return new Promise((resolve, reject) => {
  19. res.then((res) => {
  20. if (Array.isArray(res)) {
  21. if (res[0]) reject(res[0])
  22. else resolve(res[1])
  23. } else {
  24. if (typeof res == 'object' && String(res.errMsg).includes(':ok')) {
  25. resolve(res)
  26. } else {
  27. reject(res)
  28. }
  29. }
  30. });
  31. });
  32. }
  33. return res;
  34. },
  35. });
  36. // #endif
  37. }
  38. // 获取类型
  39. export const _typeof = val => Object.prototype.toString.call(val).slice(8, -1).toLowerCase()
  40. // 休眠
  41. export const sleep = ms => new Promise(r => setTimeout(r, ms))
  42. // 获取当前页面信息
  43. export const getCurrentPage = () => {
  44. const pages = getCurrentPages()
  45. return pages[pages.length - 1] || {}
  46. }
  47. // 获取当前页面 path
  48. export const getCurrentPagePath = (fullPath = false) => {
  49. const { route, $page } = getCurrentPage()
  50. return fullPath && $page?.fullPath ? $page?.fullPath : '/' + route
  51. }
  52. // 判断当前页或指定 path 是否是 tabbar 页面
  53. export const isTabBarPage = path => {
  54. const { tabBar } = pagesJson
  55. if (!tabBar) return false
  56. path = path || getCurrentPagePath()
  57. return !(!tabBar || !tabBar.list || !tabBar.list.length || tabBar.list.findIndex(i => '/' + i.pagePath == path) == -1)
  58. }
  59. // 获取应用运行页面信息
  60. export const getPageInfo = () => {
  61. // 获取 pages 并去重
  62. const pages = getCurrentPages().reduce((p, c) => {
  63. if (!p.find(f => f.route == c.route)) p.push(c)
  64. return p
  65. }, [])
  66. // 启动页
  67. const startPage = pagesJson.pages[0].path
  68. // tabBar
  69. const tabBarList = pagesJson.tabBar?.list || []
  70. // 首页
  71. const [page] = pages
  72. return {
  73. currentPage: pages[pages.length - 1] || {},
  74. startPage,
  75. isSharePage: pages.length == 1 && page.route != startPage && !tabBarList.some(i => i.pagePath == page.route),
  76. pageStackLen: pages.length,
  77. }
  78. }
  79. /**
  80. * @desc 倒计时
  81. * @func countDown
  82. * @param {String | Number} endTime 结束时间
  83. * @param {Function} callback 倒计时字符串更新回调函数 (info, isEnd) => {}
  84. * @param {String} formatStr 倒计时字符串显示格式 d=天, h=时, m=分, s=秒, 默认(hh:mm:ss)
  85. * @param {Number} refreshRate 更新频率 默认(100)
  86. * @return {Number} 定时器 id 用于结束倒计时
  87. */
  88. export const countDown = function(endTime, callback, formatStr = 'hh:mm:ss', refreshRate = 100) {
  89. const targetTime = new Date(endTime).getTime();
  90. let cacheStr
  91. const intervalId = setInterval(function() {
  92. const currentTime = new Date().getTime();
  93. const distance = targetTime - currentTime;
  94. const date = {
  95. d: Math.floor(distance / (1000 * 60 * 60 * 24)),
  96. h: Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
  97. m: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)),
  98. s: Math.floor((distance % (1000 * 60)) / 1000)
  99. }
  100. if (!formatStr.includes('d')) {
  101. date.h += date.d * 24;
  102. date.d = 0;
  103. }
  104. if (!formatStr.includes('h')) {
  105. date.m += date.h * 60;
  106. date.h = 0;
  107. }
  108. if (!formatStr.includes('m')) {
  109. date.s += date.m * 60;
  110. date.m = 0;
  111. }
  112. let str = formatStr
  113. Object.keys(date).forEach(key => {
  114. if (date[key] < 0) date[key] = 0
  115. if (str.includes(key)) {
  116. if (str.includes(key + key)) {
  117. str = str.replace(key + key, date[key].toString().padStart(2, 0))
  118. } else {
  119. str = str.replace(key, date[key])
  120. }
  121. }
  122. })
  123. if (cacheStr != str) {
  124. cacheStr = str
  125. if (date.d + date.h + date.m + date.s <= 0) {
  126. clearInterval(intervalId);
  127. callback && callback({ str, ...date }, true)
  128. } else {
  129. callback && callback({ str, ...date }, false)
  130. }
  131. }
  132. }, refreshRate);
  133. return intervalId
  134. }
  135. /**
  136. * @desc 轮询函数(等待结果)
  137. * @func pollingForResult
  138. * @param {Function} fun 返回值为 Promise 的函数
  139. * @param {Array} params fun函数调用的参数列表 ( 例: [param,param] )
  140. * @param {Function} judgeFun 拿到 fun 函数返回结果 res, 然后调用 judgeFun(res), judgeFun函数应返回 success 或 fail , 没有返回值即忽略本次
  141. * @param {Number} ms 最快多长时间调用一次 ( 默认 1000ms )
  142. * @param {Number} timeout 超时时间 ( 默认 1min )
  143. * @return {Promise} judgeFun 函数返回 success 或 fail 的调用结果
  144. */
  145. export const pollingForResult = function(fun, params, judgeFun, ms = 1000, timeout = 1000 * 60) {
  146. // console.time('polling-time')
  147. console.log('polling-params', arguments);
  148. let startTime = Date.now()
  149. let prevCallTime = 0
  150. if (typeof judgeFun != 'function') throw new Error('judgeFun 参数应为一个 function');
  151. if (!(params instanceof Array)) params = [params]
  152. if (ms <= 0) ms = 1
  153. return new Promise((resolve, reject) => {
  154. function fun_call() {
  155. if ((prevCallTime + ms) > Date.now()) {
  156. setTimeout(() => {
  157. fun_call()
  158. }, (prevCallTime + ms) - Date.now());
  159. return
  160. }
  161. if ((timeout + startTime) < Date.now()) {
  162. reject('Timeout')
  163. return
  164. }
  165. prevCallTime = Date.now()
  166. // console.time('fun-call-time')
  167. fun(...params).then(res => {
  168. console.log('fun-call-res', res);
  169. // console.timeEnd('fun-call-time')
  170. if (judgeFun(res) === 'success') {
  171. resolve(res)
  172. // console.timeEnd('polling-time')
  173. } else if (judgeFun(res) === 'fail') {
  174. reject(res)
  175. // console.timeEnd('polling-time')
  176. } else {
  177. fun_call()
  178. }
  179. }).catch(err => {
  180. console.log('fun-call-err', err);
  181. // console.timeEnd('fun-call-time')
  182. fun_call()
  183. })
  184. }
  185. fun_call()
  186. })
  187. }
  188. /**
  189. * @desc 轮询函数(获取数据)
  190. * @func pollingForData
  191. * @param {Function} fun 返回值为 Promise 的函数
  192. * @param {Array} params fun函数调用的参数列表 ( 例: [param,param] )
  193. * @param {Function} callback 每次调用的结果 ( 例: (err, res, count) => {} )
  194. * @param {Number} ms 最快多长时间调用一次 ( 默认 1000ms )
  195. * @return {Function} 结束轮询函数
  196. */
  197. export const pollingForData = function(fun, params, callback, ms = 1000) {
  198. console.log('polling-params', arguments);
  199. let prevCallTime = 0
  200. let endFlag = false
  201. let count = 0
  202. if (typeof callback != 'function') throw new Error('callback 参数应为一个 function');
  203. if (!(params instanceof Array)) params = [params]
  204. if (ms <= 0) ms = 1
  205. function fun_call() {
  206. if (endFlag) return
  207. if ((prevCallTime + ms) > Date.now()) {
  208. setTimeout(() => {
  209. fun_call()
  210. }, (prevCallTime + ms) - Date.now());
  211. return
  212. }
  213. prevCallTime = Date.now()
  214. count++
  215. fun(...params).then(res => {
  216. callback && callback(null, res, count)
  217. fun_call()
  218. }).catch(err => {
  219. callback && callback(err, null, count)
  220. fun_call()
  221. })
  222. }
  223. fun_call()
  224. return () => {
  225. console.log('polling-end');
  226. endFlag = true
  227. }
  228. }
  229. /**
  230. * @desc 深拷贝
  231. * @func deepClone
  232. * @param {Object} target 被拷贝的对象
  233. * @return {Object} 新对象
  234. */
  235. export const deepClone = (target, map = new WeakMap()) => {
  236. if (target === null || typeof target !== 'object') {
  237. return target;
  238. }
  239. if (target instanceof Date) {
  240. return new Date(target);
  241. }
  242. if (target instanceof RegExp) {
  243. return new RegExp(target.source, target.flags);
  244. }
  245. if (target instanceof Map) {
  246. const newMap = new Map();
  247. target.forEach((value, key) => {
  248. newMap.set(deepClone(key, map), deepClone(value, map));
  249. });
  250. return newMap;
  251. }
  252. if (target instanceof Set) {
  253. const newSet = new Set();
  254. target.forEach(value => {
  255. newSet.add(deepClone(value, map));
  256. });
  257. return newSet;
  258. }
  259. if (typeof target === 'function') {
  260. return target;
  261. }
  262. if (map.has(target)) {
  263. return map.get(target);
  264. }
  265. const cloneTarget = Array.isArray(target) ? [] : {};
  266. map.set(target, cloneTarget);
  267. const symbolKeys = Object.getOwnPropertySymbols(target);
  268. if (symbolKeys.length > 0) {
  269. symbolKeys.forEach(symKey => {
  270. cloneTarget[symKey] = deepClone(target[symKey], map);
  271. });
  272. }
  273. for (let key in target) {
  274. if (Object.prototype.hasOwnProperty.call(target, key)) {
  275. cloneTarget[key] = deepClone(target[key], map);
  276. }
  277. }
  278. return cloneTarget;
  279. }