util.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. const extend = function extend(target) {
  2. var sources = Array.prototype.slice.call(arguments, 1)
  3. for (var i = 0; i < sources.length; i += 1) {
  4. var source = sources[i]
  5. for (var key in source) {
  6. if (source.hasOwnProperty(key)) {
  7. target[key] = source[key]
  8. }
  9. }
  10. }
  11. return target
  12. }
  13. /**
  14. * 获取当前时间戳
  15. */
  16. const getTimestamp = (date) => {
  17. date = date || new Date()
  18. return Math.round(date / 1000)
  19. }
  20. /**
  21. * 保留指定小数位
  22. */
  23. const toDecimal = (float, num) => {
  24. if (typeof float !== 'number') float = parseFloat(float)
  25. return parseFloat(float.toFixed(num))
  26. }
  27. /**
  28. * 时间戳转 yyyy-MM-dd hh:mm
  29. */
  30. export function formatDate(timestamp, format) {
  31. const date = timestamp ? new Date(timestamp * 1000) : new Date();
  32. const data = {
  33. 'M+': date.getMonth() + 1,
  34. 'd+': date.getDate(),
  35. 'h+': date.getHours(),
  36. 'm+': date.getMinutes(),
  37. 's+': date.getSeconds(),
  38. 'q+': Math.floor((date.getMonth() + 3) / 3),
  39. 'S+': date.getMilliseconds()
  40. }
  41. if (/(y+)/i.test(format)) {
  42. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  43. }
  44. for (var key in data) {
  45. if (new RegExp('(' + key + ')').test(format)) {
  46. format = format.replace(RegExp.$1, RegExp.$1.length == 1 ?
  47. data[key] : ('00' + data[key]).substr(('' + data[key]).length))
  48. }
  49. }
  50. return format
  51. }
  52. /**
  53. * 分钟、小时、天前的处理
  54. */
  55. const timeAgo = function(timestamp, format) {
  56. const minute = 1000 * 60 // 把分,时,天,周,半个月,一个月用毫秒表示
  57. const hour = minute * 60
  58. const day = hour * 24
  59. const now = new Date().getTime() // 获取当前时间毫秒
  60. const spreadTime = now - timestamp * 1000 // 时间差
  61. if (spreadTime < 0) {
  62. return
  63. }
  64. const minC = spreadTime / minute
  65. const hourC = spreadTime / hour
  66. const dayC = spreadTime / day
  67. let result
  68. if (spreadTime >= 0 && spreadTime <= minute) {
  69. result = '刚刚'
  70. } else if (minC >= 1 && minC <= 59) {
  71. result = parseInt(minC) + '分钟前'
  72. } else if (hourC >= 1 && hourC <= 23) {
  73. result = parseInt(hourC) + '小时前'
  74. } else if (dayC >= 1 && dayC < 3) {
  75. result = parseInt(dayC) + '天前'
  76. } else if (dayC >= 3 && dayC <= 7) {
  77. result = '3天前'
  78. } else {
  79. result = formatDate(timestamp, format)
  80. }
  81. return result
  82. }
  83. /**
  84. * param 将要转为URL参数字符串的对象
  85. * key URL参数字符串的前缀
  86. * encode true/false 是否进行URL编码,默认为true
  87. *
  88. * return URL参数字符串
  89. */
  90. const urlEncode = (param, key, encode) => {
  91. if (param == null) return ''
  92. const t = typeof(param)
  93. let paramStr = ''
  94. if (t === 'string' || t === 'number' || t === 'boolean') {
  95. paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param)
  96. } else {
  97. for (let i in param) {
  98. let k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '[' + i + ']')
  99. paramStr += urlEncode(param[i], k, encode)
  100. }
  101. }
  102. return paramStr
  103. }
  104. /**
  105. * return
  106. */
  107. const urlDecode = (query) => {
  108. if (!query) return null
  109. let hash, object = {}
  110. const hashes = query.slice(query.indexOf('?') + 1).split('&')
  111. for (let i = 0; i < hashes.length; i++) {
  112. hash = hashes[i].split('=')
  113. object[hash[0]] = hash[1]
  114. }
  115. return object;
  116. }
  117. /**
  118. * 对象合并
  119. */
  120. const deepAssign = (origin, source) => {
  121. for (let key in source) {
  122. if (source.hasOwnProperty(key)) {
  123. if (source[key] instanceof Object) {
  124. deepAssign(origin[key], source[key])
  125. } else {
  126. origin[key] = source[key]
  127. }
  128. }
  129. }
  130. }
  131. /**
  132. * 状态数据
  133. */
  134. const display = {
  135. toast: false, // 无用
  136. modal: false,
  137. loading: false,
  138. }
  139. // 显示消息提示
  140. const showToast = function(text, icon) {
  141. wx.showToast({
  142. title: text || '加载中',
  143. icon: icon || 'none',
  144. mask: true,
  145. duration: 2000
  146. })
  147. }
  148. // 隐藏消息提示
  149. const hideToast = function() {
  150. wx.hideToast()
  151. }
  152. // 显示 loading
  153. const showLoading = function(text) {
  154. if (!display.loading) {
  155. display.loading = true
  156. wx.showLoading({
  157. title: text || '加载中',
  158. mask: true
  159. })
  160. }
  161. }
  162. // 隐藏 loading
  163. const hideLoading = function() {
  164. if (display.loading) {
  165. display.loading = false
  166. wx.hideLoading()
  167. }
  168. }
  169. // 显示失败提示
  170. const showModal = (title, content) => {
  171. if (display.toast) hideToast()
  172. if (display.loading) hideLoading()
  173. if (!display.modal) {
  174. title = title || '信息提示'
  175. content = content || '未知错误' // content 为 null 时会报错
  176. display.modal = true
  177. wx.showModal({
  178. title,
  179. content: typeof content === 'object' ? JSON.stringify(content) : content,
  180. showCancel: false,
  181. confirmColor: '#3B99FC',
  182. complete: function(e) {
  183. display.modal = false
  184. }
  185. })
  186. }
  187. }
  188. export function buildPageUrl(page, options) {
  189. let pageUrl = page;
  190. if (options) {
  191. let params = urlEncode(options)
  192. pageUrl += '?' + params.substring(1, params.length);
  193. }
  194. return pageUrl;
  195. }
  196. export function encodeRedirectUrl(page, options) {
  197. return encodeURIComponent(buildPageUrl(page, options));
  198. }
  199. export function decodeRedirectUrl(url) {
  200. return decodeURIComponent(url);
  201. }
  202. /**
  203. * 处理富文本里的图片宽度自适应
  204. * 1.去掉img标签里的style、width、height属性
  205. * 2.img标签添加style属性:max-width:100%;height:auto
  206. * 3.修改所有style里的width属性为max-width:100%
  207. * 4.去掉<br/>标签
  208. *
  209. * @param html
  210. * @returns {void|string|*}
  211. */
  212. export function formatRichText(html) {
  213. let newContent = html.replace(/<img[^>]*>/gi, function(match, capture) {
  214. match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
  215. match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
  216. match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
  217. return match;
  218. });
  219. newContent = newContent.replace(/style="[^"]+"/gi, function(match, capture) {
  220. match = match.replace(/width:[^;]+;/gi, 'max-width:100%;').replace(/width:[^;]+;/gi, 'max-width:100%;');
  221. return match;
  222. });
  223. newContent = newContent.replace(/<br[^>]*\/>/gi, '');
  224. newContent = newContent.replace(/\<img/gi, '<img style="max-width:100%;height:auto;display:block;margin:10px 0;"');
  225. return newContent;
  226. }
  227. function strlen(value) {
  228. //中文、中文标点、全角字符按1长度,英文、英文符号、数字按0.5长度计算
  229. let cnReg = /([\u4e00-\u9fa5]|[\u3000-\u303F]|[\uFF00-\uFF60])/g;
  230. let mat = value.match(cnReg);
  231. let length = 0;
  232. if (mat) {
  233. return (length = mat.length + (value.length - mat.length) * 0.5);
  234. } else {
  235. return (length = value.length * 0.5);
  236. }
  237. }
  238. /**
  239. *
  240. * 判断是否在微信浏览器 true是
  241. */
  242. function isWeiXinBrowser() {
  243. // #ifdef H5
  244. let ua = window.navigator.userAgent.toLowerCase()
  245. if (ua.match(/MicroMessenger/i) == 'micromessenger') {
  246. return true
  247. } else {
  248. return false
  249. }
  250. // #endif
  251. return false
  252. }
  253. /**
  254. * 获取url参数
  255. * @param {*} name
  256. * @param {*}
  257. * @returns
  258. */
  259. function getQueryString(name, url) {
  260. var url = url || window.location.href
  261. var reg = new RegExp('(^|&|/?)' + name + '=([^&|/?]*)(&|/?|$)', 'i')
  262. var r = url.substr(1).match(reg)
  263. if (r != null) {
  264. return r[2]
  265. }
  266. return null
  267. }
  268. //路径转化
  269. function getPath(path) {
  270. return path ? path.split('?').shift() : path;
  271. }
  272. //复制内容
  273. function uniCopy({
  274. content,
  275. success,
  276. error
  277. }) {
  278. content = typeof content === 'string' ? content : content.toString() // 复制内容,必须字符串,数字需要转换为字符串
  279. /**
  280. * 小程序端 和 app端的复制逻辑
  281. */
  282. //#ifndef H5
  283. uni.setClipboardData({
  284. data: content,
  285. success: function() {
  286. success("复制成功~")
  287. },
  288. fail: function() {
  289. error("复制失败~")
  290. }
  291. });
  292. //#endif
  293. /**
  294. * H5端的复制逻辑
  295. */
  296. // #ifdef H5
  297. if (!document.queryCommandSupported('copy')) { //为了兼容有些浏览器 queryCommandSupported 的判断
  298. // 不支持
  299. error('浏览器不支持')
  300. }
  301. let textarea = document.createElement("textarea")
  302. textarea.value = content
  303. textarea.readOnly = "readOnly"
  304. document.body.appendChild(textarea)
  305. textarea.select() // 选择对象
  306. textarea.setSelectionRange(0, content.length) //核心
  307. let result = document.execCommand("copy") // 执行浏览器复制命令
  308. if (result) {
  309. success("复制成功~")
  310. } else {
  311. error("复制失败,请检查h5中调用该方法的方式,是不是用户点击的方式调用的,如果不是请改为用户点击的方式触发该方法,因为h5中安全性,不能js直接调用!")
  312. }
  313. textarea.remove()
  314. // #endif
  315. }
  316. //设置缓存
  317. function setDb(name, value, db_time = 7200) {
  318. let time = (new Date()).getTime();
  319. let data = {
  320. value: value,
  321. time: time,
  322. db_time: db_time
  323. }
  324. uni.setStorageSync(name, data);
  325. }
  326. //获取缓存
  327. function getDb(name) {
  328. try {
  329. let res = uni.getStorageSync(name);
  330. if (!res) {
  331. return '';
  332. }
  333. let time = (new Date()).getTime();
  334. if ((time - res.time) / 1000 >= res.db_time) {
  335. uni.removeStorageSync(name);
  336. return '';
  337. }
  338. return res.value;
  339. } catch (e) {
  340. //TODO handle the exception
  341. return '';
  342. }
  343. }
  344. /**
  345. * 下载图片
  346. */
  347. function getCachedImage(image_url) {
  348. return new Promise((resolve, reject) => {
  349. let arr = image_url.split('/');
  350. let image_name = arr[arr.length - 1];
  351. var u = getDb('cms' + image_name);
  352. if (u) {
  353. resolve(u);
  354. } else {
  355. // 本地没有缓存 需要下载
  356. uni.downloadFile({
  357. url: image_url,
  358. success: res => {
  359. if (res.statusCode === 200) {
  360. uni.saveFile({
  361. tempFilePath: res.tempFilePath,
  362. success: function(res) {
  363. setDb('cms' + image_name, res.savedFilePath)
  364. resolve(res.savedFilePath);
  365. }
  366. });
  367. } else {
  368. reject('下载失败');
  369. }
  370. },
  371. fail: function() {
  372. reject('下载失败');
  373. }
  374. });
  375. }
  376. });
  377. }
  378. /**
  379. * 重设tabbar
  380. * @param {Object} tablist
  381. */
  382. function setTabbar(tablist) {
  383. tablist.list.forEach((item, index) => {
  384. uni.setTabBarItem({
  385. index: index,
  386. text: item.text,
  387. iconPath: item.image,
  388. selectedIconPath: item.selectedImage,
  389. pagePath: item.path
  390. })
  391. })
  392. uni.setTabBarStyle({
  393. color: tablist.color,
  394. selectedColor: tablist.selectColor,
  395. backgroundColor: tablist.bgColor,
  396. borderStyle: 'black'
  397. })
  398. }
  399. export default {
  400. extend,
  401. toDecimal,
  402. getTimestamp,
  403. formatDate,
  404. timeAgo,
  405. urlEncode,
  406. urlDecode,
  407. deepAssign,
  408. showToast,
  409. hideToast,
  410. showLoading,
  411. hideLoading,
  412. showModal,
  413. formatRichText,
  414. strlen,
  415. isWeiXinBrowser,
  416. getQueryString,
  417. getPath,
  418. uniCopy,
  419. setDb,
  420. getDb,
  421. getCachedImage,
  422. setTabbar,
  423. encodeRedirectUrl
  424. }