utils.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. const util = {}
  2. import t from './test.js'
  3. import i18n from '@/lang/lang.js'
  4. /**
  5. * 检查邮箱格式
  6. * @param {string} str 要验证的邮箱
  7. */
  8. util.checkmail = function(str) {
  9. let reg = t.isEmail
  10. if (!reg.test(str)) {
  11. return false
  12. } else {
  13. return true
  14. }
  15. }
  16. /**
  17. * 验证银行卡
  18. * @param {string} cardno 验证银行卡
  19. */
  20. util.checkBankCard = function(cardno) {
  21. let reg = t.bankCard
  22. if (!reg.test(cardno)) {
  23. return false
  24. } else {
  25. return true
  26. }
  27. }
  28. /**
  29. * 设置页面原生标题
  30. * @param {string} title 页面标题名称
  31. */
  32. util.setPageTitle = function(title) {
  33. let timer = null
  34. if (timer) timer = null
  35. timer = setTimeout(() => {
  36. uni.setNavigationBarTitle({
  37. title
  38. })
  39. timer = null
  40. }, 40)
  41. }
  42. /**
  43. * 判断数字是否正整数
  44. */
  45. util.isCount = function(num) {
  46. if (t.isCount.test(num)) {
  47. return true
  48. } else {
  49. return false
  50. }
  51. }
  52. /**
  53. * 显示加载框
  54. */
  55. util.showLoading = function(title, type) {
  56. // #ifdef APP-PLUS
  57. var w = plus.nativeUI.showWaiting(title || "", {
  58. width: '80px',
  59. height: '80px',
  60. loading: {
  61. type: type || 'snow',
  62. height: '40px'
  63. },
  64. background: 'rgba(0,0,0,0.9)'
  65. });
  66. // #endif
  67. // #ifndef APP-PLUS
  68. uni.showLoading({
  69. title: title || '',
  70. });
  71. // #endif
  72. }
  73. /**
  74. * 隐藏加载框
  75. */
  76. util.hideLoading = function() {
  77. // #ifdef APP-PLUS
  78. plus.nativeUI.closeWaiting();
  79. // #endif
  80. // #ifndef APP-PLUS
  81. uni.hideLoading();
  82. // #endif
  83. }
  84. /**
  85. * 要复制的内容
  86. * NJS设置剪切板
  87. */
  88. util.setClipboardData = function(string, callback) {
  89. const appPlatform = uni.getSystemInfoSync().platform
  90. // #ifdef APP-PLUS
  91. if (appPlatform == "ios") {
  92. var UIPasteboard = plus.ios.importClass("UIPasteboard");
  93. var generalPasteboard = UIPasteboard.generalPasteboard();
  94. // 设置
  95. generalPasteboard.setValueforPasteboardType(string, "public.utf8-plain-text");
  96. callback && callback({
  97. code: 1
  98. });
  99. } else {
  100. var Context = plus.android.importClass("android.content.Context");
  101. var main = plus.android.runtimeMainActivity();
  102. var clip = main.getSystemService(Context.CLIPBOARD_SERVICE);
  103. plus.android.invoke(clip, "setText", string);
  104. callback && callback({
  105. code: 1
  106. });
  107. }
  108. // #endif
  109. }
  110. /**
  111. * njs 获取剪切板
  112. */
  113. util.getClipboardData = function(callback) {
  114. const appPlatform = uni.getSystemInfoSync().platform
  115. // #ifdef APP-PLUS
  116. if (appPlatform == "ios") {
  117. var UIPasteboard = plus.ios.importClass("UIPasteboard");
  118. var generalPasteboard = UIPasteboard.generalPasteboard();
  119. // 获取
  120. var value = generalPasteboard.valueForPasteboardType("public.utf8-plain-text");
  121. callback && callback({
  122. code: 1,
  123. data: value
  124. });
  125. } else {
  126. var Context = plus.android.importClass("android.content.Context");
  127. var main = plus.android.runtimeMainActivity();
  128. var clip = main.getSystemService(Context.CLIPBOARD_SERVICE);
  129. var value = plus.android.invoke(clip, "getText");
  130. callback && callback({
  131. code: 1,
  132. data: value
  133. });
  134. }
  135. // #endif
  136. }
  137. /**
  138. * 复制插件
  139. * params:
  140. * content 要复制的内容
  141. * success
  142. * error
  143. */
  144. util.copy = function({
  145. content,
  146. success,
  147. error
  148. }) {
  149. if (!content) return error('复制的内容不能为空 !')
  150. content = typeof content === 'string' ? content : content.toString() // 复制内容,必须字符串,数字需要转换为字符串
  151. /**
  152. * 小程序端 和 app端的复制逻辑
  153. */
  154. //#ifndef H5
  155. uni.setClipboardData({
  156. data: content,
  157. success: function() {
  158. success("复制成功~")
  159. console.log('success');
  160. },
  161. fail: function() {
  162. success("复制失败~")
  163. }
  164. });
  165. //#endif
  166. /**
  167. * H5端的复制逻辑
  168. */
  169. // #ifdef H5
  170. if (!document.queryCommandSupported('copy')) { //为了兼容有些浏览器 queryCommandSupported 的判断
  171. // 不支持
  172. error('浏览器不支持')
  173. }
  174. let textarea = document.createElement("textarea")
  175. textarea.value = content
  176. textarea.readOnly = "readOnly"
  177. document.body.appendChild(textarea)
  178. textarea.select() // 选择对象
  179. textarea.setSelectionRange(0, content.length) //核心
  180. let result = document.execCommand("copy") // 执行浏览器复制命令
  181. if (result) {
  182. success("复制成功~")
  183. } else {
  184. error("复制失败,请检查h5中调用该方法的方式,是不是用户点击的方式调用的,如果不是请改为用户点击的方式触发该方法,因为h5中安全性,不能js直接调用!")
  185. }
  186. textarea.remove()
  187. // #endif
  188. }
  189. /**
  190. * 小程序获取摄像头权限
  191. */
  192. util.cameraScan = function(callback) {
  193. uni.authorize({
  194. scope: 'scope.camera',
  195. success() {
  196. uni.scanCode({
  197. onlyFromCamera: true,
  198. scanType: ['barCode'],
  199. success: function(data) {
  200. callback && callback({
  201. data
  202. })
  203. }
  204. });
  205. },
  206. fail(e) {
  207. uni.showModal({
  208. content: '当前摄像头未授权该小程序,是否去授权?',
  209. success: function(res) {
  210. if (res.confirm) {
  211. // #ifdef MP-WEIXIN
  212. uni.openSetting({
  213. success(res) {
  214. if (res.authSetting['scope.camera']) {
  215. uni.showToast({
  216. title: '已授权',
  217. icon: 'success'
  218. });
  219. }
  220. }
  221. });
  222. // #endif
  223. }
  224. }
  225. });
  226. }
  227. });
  228. }
  229. /**
  230. * 小程序获取位置权限
  231. */
  232. util.localtion = function(callback) {
  233. uni.authorize({
  234. scope: 'scope.userLocation',
  235. success() {
  236. return true
  237. },
  238. fail(e) {
  239. uni.showModal({
  240. content: '定位未授权该小程序,是否去授权?',
  241. success: function(res) {
  242. if (res.confirm) {
  243. // #ifdef MP-WEIXIN
  244. uni.openSetting({
  245. success(res) {
  246. if (res.authSetting['scope.userLocation']) {
  247. uni.showToast({
  248. title: '已授权',
  249. icon: 'success'
  250. });
  251. return true
  252. }
  253. }
  254. });
  255. // #endif
  256. } else {
  257. return false
  258. }
  259. }
  260. });
  261. }
  262. });
  263. }
  264. /**
  265. * 提示消息
  266. * @param {Object} msg
  267. */
  268. util.showToast = function(msg, type = 'none', path) {
  269. uni.showToast({
  270. title: msg,
  271. mask: true,
  272. duration: 2000,
  273. icon: type
  274. });
  275. }
  276. /**
  277. * 字数过长,则超出部分用省略号显示
  278. * @param {String} str 当前要处理的字符串
  279. * @param {Number} len 显示的预期长度(字数)
  280. */
  281. util.cutString = function(str, len) {
  282. //length属性读出来的汉字长度为1
  283. if (str.length * 2 <= len) {
  284. return str;
  285. }
  286. var strlen = 0;
  287. var s = "";
  288. for (var i = 0; i < str.length; i++) {
  289. s = s + str.charAt(i);
  290. if (str.charCodeAt(i) > 128) {
  291. strlen = strlen + 2;
  292. if (strlen >= len) {
  293. return s.substring(0, s.length - 1) + "...";
  294. }
  295. } else {
  296. strlen = strlen + 1;
  297. if (strlen >= len) {
  298. return s.substring(0, s.length - 2) + "...";
  299. }
  300. }
  301. }
  302. return s
  303. }
  304. /**
  305. * 提取数组对象中某个键值,重新组成新的数组
  306. * @param {Array} arr 当前要处理的数组
  307. * @param {String} prop 要提取的键
  308. * return 返回新的数组
  309. */
  310. util.extractProps = function(arr, prop) {
  311. return arr.map((item) => item[prop]);
  312. }
  313. /**
  314. * 判断某个变量的值是否为数字类型
  315. * @param {any} value 当前要判读的值
  316. * return 返回布尔类型 true 为数字,false 为非数字
  317. */
  318. util.isNumber = function(value) {
  319. return typeof value === 'number' && !isNaN(value);
  320. }
  321. /**
  322. * 四舍五入保留2为小数,不够2为小数补0
  323. * @param {Number/String} value 当前的值
  324. * * @param {Number/String} type 是否四舍五入 floor:不; round:是
  325. * return 返回字符串 如10.00
  326. */
  327. util.float = function(value, type = 'round') {
  328. var value = Math[type](parseFloat(value) * 100) / 100;
  329. var s = value.toString().split(".");
  330. if (s.length == 1) {
  331. value = value.toString() + ".00";
  332. return value;
  333. }
  334. if (s.length > 1) {
  335. if (s[1].length < 2) {
  336. value = value.toString() + "0";
  337. }
  338. return value;
  339. }
  340. }
  341. /**
  342. * 深度判断2个对象是否完全相等
  343. * @param {Object} x 当前要判读的第一个对象
  344. * @param {Object} y 当前要判读的第二个对象
  345. * return 返回布尔类型 true 为相等,false 为不相等
  346. */
  347. util.deepCompare = function(x, y) {
  348. var i, l, leftChain, rightChain;
  349. function compare2Objects(x, y) {
  350. var p;
  351. if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
  352. return true;
  353. }
  354. if (x === y) {
  355. return true;
  356. }
  357. if ((typeof x === 'function' && typeof y === 'function') ||
  358. (x instanceof Date && y instanceof Date) ||
  359. (x instanceof RegExp && y instanceof RegExp) ||
  360. (x instanceof String && y instanceof String) ||
  361. (x instanceof Number && y instanceof Number)) {
  362. return x.toString() === y.toString();
  363. }
  364. if (!(x instanceof Object && y instanceof Object)) {
  365. return false;
  366. }
  367. if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
  368. return false;
  369. }
  370. if (x.constructor !== y.constructor) {
  371. return false;
  372. }
  373. if (x.prototype !== y.prototype) {
  374. return false;
  375. }
  376. if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
  377. return false;
  378. }
  379. for (p in y) {
  380. if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
  381. return false;
  382. } else if (typeof y[p] !== typeof x[p]) {
  383. return false;
  384. }
  385. }
  386. for (p in x) {
  387. if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
  388. return false;
  389. } else if (typeof y[p] !== typeof x[p]) {
  390. return false;
  391. }
  392. switch (typeof(x[p])) {
  393. case 'object':
  394. case 'function':
  395. leftChain.push(x);
  396. rightChain.push(y);
  397. if (!compare2Objects(x[p], y[p])) {
  398. return false;
  399. }
  400. leftChain.pop();
  401. rightChain.pop();
  402. break;
  403. default:
  404. if (x[p] !== y[p]) {
  405. return false;
  406. }
  407. break;
  408. }
  409. }
  410. return true;
  411. }
  412. if (arguments.length < 1) {
  413. return true;
  414. }
  415. for (i = 1, l = arguments.length; i < l; i++) {
  416. leftChain = [];
  417. rightChain = [];
  418. if (!compare2Objects(arguments[0], arguments[i])) {
  419. return false;
  420. }
  421. }
  422. return true;
  423. }
  424. /**
  425. * 判断数组中所有元素是否完全相同
  426. * @param {Array} array 当前数组
  427. * return 返回布尔类型 true 为全相同,false 为不全相同
  428. */
  429. util.isAllEqual = function(array) {
  430. if (array.length > 0) {
  431. return !array.some(item => item !== array[0]);
  432. } else {
  433. return true
  434. }
  435. }
  436. /**
  437. * 数据分组
  438. * @param {Array} oArr - 原数组列表
  439. * @param {Number} length - 单个数组长度
  440. * @return {Array} arr - 分组后的新数组
  441. */
  442. util.splitData = function(oArr = [], length = 1) {
  443. let arr = [];
  444. let minArr = [];
  445. oArr.forEach(c => {
  446. if (minArr.length === length) {
  447. minArr = [];
  448. }
  449. if (minArr.length === 0) {
  450. arr.push(minArr);
  451. }
  452. minArr.push(c);
  453. });
  454. return arr;
  455. }
  456. /**
  457. * 剩余时间格式化
  458. * @param {Number} t - 剩余多少秒
  459. * @return {Object} format - 格式后的天时分秒对象
  460. */
  461. util.format = function(t) {
  462. let format = {
  463. d: '00',
  464. h: '00',
  465. m: '00',
  466. s: '00'
  467. };
  468. if (t > 0) {
  469. let d = Math.floor(t / 86400);
  470. let h = Math.floor((t / 3600) % 24);
  471. let m = Math.floor((t / 60) % 60);
  472. let s = Math.floor(t % 60);
  473. format.d = d < 10 ? '0' + d : d;
  474. format.h = h < 10 ? '0' + h : h;
  475. format.m = m < 10 ? '0' + m : m;
  476. format.s = s < 10 ? '0' + s : s;
  477. }
  478. return format;
  479. }
  480. /**
  481. * 打电话
  482. * @param {String<Number>} phoneNumber - 数字字符串
  483. */
  484. util.callPhone = function(phoneNumber = '') {
  485. let num = phoneNumber.toString()
  486. uni.makePhoneCall({
  487. phoneNumber: num,
  488. fail(err) {
  489. console.log('makePhoneCall出错', err)
  490. },
  491. });
  492. }
  493. /**
  494. * 号码部分数字*代替
  495. * @param {String<Number>} str - 要进行隐藏的变量
  496. * @param {String<Number>} frontLen - 前面需要保留几位,默认前2位
  497. * @param {String<Number>} endLen - 后面需要保留几位,默认后2位
  498. */
  499. util.hiddenCardId = function (str, frontLen = 2, endLen = 2) {
  500. let len = str.length - frontLen - endLen;
  501. let start = '';
  502. for (let i = 0; i < len; i++) {
  503. start += '*';
  504. }
  505. // 最后的返回值由三部分组成
  506. return str.substring(0, frontLen) + start + str.substring(str.length - endLen);
  507. }
  508. /**
  509. * 节流
  510. * 在给定时间内只有第一次的操作会返回结果
  511. * 结合了防抖的思路:在delay时间内生成定时器,一旦到了delay的时间就返回结果
  512. * 当用户只点击了一次的时候,在delay时间后得到结果
  513. * 当用户点击了多次的时候,在delay时间后得到第一次的结果,其余的被节流阀忽视掉
  514. * @param {Function} fn 要包装的回调函数
  515. * @param {number} delay 延迟时间,单位ms,默认500
  516. * @return {Function} 被节流函数劫持的新的函数
  517. */
  518. util.throttle = function (fn, delay = 500) {
  519. let last = 0;
  520. let timer = null;
  521. return function () {
  522. let args = arguments;
  523. let now = +new Date();
  524. let context = this;
  525. if (now - last < delay) {
  526. clearTimeout(timer);
  527. timer = setTimeout(() => {
  528. last = now;
  529. fn.apply(context, args);
  530. }, delay);
  531. } else {
  532. last = now;
  533. fn.apply(context, args);
  534. }
  535. }
  536. }
  537. /**
  538. * 防抖
  539. * 在delay时间后得到结果
  540. * 如果没等到delay的时间一直触发则永远也得不到结果
  541. * @param {Function} fn 要包装的回调函数
  542. * @param {number} delay 延迟时间,单位ms,默认500
  543. * @return {Function} 被防抖函数劫持的新的函数
  544. */
  545. util.debounce = function (fn, delay = 500) {
  546. let timer = null;
  547. return function () {
  548. let args = arguments;
  549. if(timer) {
  550. clearTimeout(timer);
  551. }
  552. timer = setTimeout(() => {
  553. fn.apply(this, args);
  554. }, delay);
  555. }
  556. }
  557. export default util