util.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. import {
  2. TOKENNAME,
  3. HTTP_REQUEST_URL
  4. } from '../config/app.js';
  5. import store from '../store';
  6. import {
  7. pathToBase64
  8. } from '@/plugin/image-tools/index.js';
  9. // #ifdef APP-PLUS
  10. import permision from "./permission.js"
  11. // #endif
  12. export default {
  13. /**
  14. * 字符串截取
  15. * @obj 传入的数据
  16. * @state 0 某个参数之前 1某个参数之后
  17. *
  18. *
  19. * **/
  20. stringIntercept: function(obj, state, type) {
  21. var index = obj.lastIndexOf(type);
  22. if (state == 0) {
  23. obj = obj.substring(0, index);
  24. } else {
  25. obj = obj.substring(index + 1, obj.length);
  26. }
  27. return obj;
  28. },
  29. /**
  30. * opt object | string
  31. * to_url object | string
  32. * 例:
  33. * this.Tips('/pages/test/test'); 跳转不提示
  34. * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
  35. * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
  36. * tab=1 一定时间后跳转至 table上
  37. * tab=2 一定时间后跳转至非 table上
  38. * tab=3 一定时间后返回上页面
  39. * tab=4 关闭所有页面跳转至非table上
  40. * tab=5 关闭当前页面跳转至table上
  41. */
  42. Tips: function(opt, to_url) {
  43. if (typeof opt == 'string') {
  44. to_url = opt;
  45. opt = {};
  46. }
  47. let title = opt.title || '',
  48. icon = opt.icon || 'none',
  49. endtime = opt.endtime || 2000,
  50. success = opt.success;
  51. if (title) uni.showToast({
  52. title: title,
  53. icon: icon,
  54. duration: endtime,
  55. success
  56. })
  57. if (to_url != undefined) {
  58. if (typeof to_url == 'object') {
  59. let tab = to_url.tab || 1,
  60. url = to_url.url || '';
  61. switch (tab) {
  62. case 1:
  63. //一定时间后跳转至 table
  64. setTimeout(function() {
  65. uni.switchTab({
  66. url: url
  67. })
  68. }, endtime);
  69. break;
  70. case 2:
  71. //跳转至非table页面
  72. setTimeout(function() {
  73. uni.navigateTo({
  74. url: url,
  75. })
  76. }, endtime);
  77. break;
  78. case 3:
  79. //返回上页面
  80. setTimeout(function() {
  81. // #ifndef H5
  82. uni.navigateBack({
  83. delta: parseInt(url),
  84. })
  85. // #endif
  86. // #ifdef H5
  87. history.back();
  88. // #endif
  89. }, endtime);
  90. break;
  91. case 4:
  92. //关闭当前所有页面跳转至非table页面
  93. setTimeout(function() {
  94. uni.reLaunch({
  95. url: url,
  96. })
  97. }, endtime);
  98. break;
  99. case 5:
  100. //关闭当前页面跳转至非table页面
  101. setTimeout(function() {
  102. uni.redirectTo({
  103. url: url,
  104. })
  105. }, endtime);
  106. break;
  107. }
  108. } else if (typeof to_url == 'function') {
  109. setTimeout(function() {
  110. to_url && to_url();
  111. }, endtime);
  112. } else {
  113. //没有提示时跳转不延迟
  114. setTimeout(function() {
  115. uni.navigateTo({
  116. url: to_url,
  117. })
  118. }, title ? endtime : 0);
  119. }
  120. }
  121. },
  122. /**
  123. * 移除数组中的某个数组并组成新的数组返回
  124. * @param array array 需要移除的数组
  125. * @param int index 需要移除的数组的键值
  126. * @param string | int 值
  127. * @return array
  128. *
  129. */
  130. ArrayRemove: function(array, index, value) {
  131. const valueArray = [];
  132. if (array instanceof Array) {
  133. for (let i = 0; i < array.length; i++) {
  134. if (typeof index == 'number' && array[index] != i) {
  135. valueArray.push(array[i]);
  136. } else if (typeof index == 'string' && array[i][index] != value) {
  137. valueArray.push(array[i]);
  138. }
  139. }
  140. }
  141. return valueArray;
  142. },
  143. /**
  144. * 生成海报获取文字
  145. * @param string text 为传入的文本
  146. * @param int num 为单行显示的字节长度
  147. * @return array
  148. */
  149. textByteLength: function(text, num) {
  150. let strLength = 0;
  151. let rows = 1;
  152. let str = 0;
  153. let arr = [];
  154. for (let j = 0; j < text.length; j++) {
  155. if (text.charCodeAt(j) > 255) {
  156. strLength += 2;
  157. if (strLength > rows * num) {
  158. strLength++;
  159. arr.push(text.slice(str, j));
  160. str = j;
  161. rows++;
  162. }
  163. } else {
  164. strLength++;
  165. if (strLength > rows * num) {
  166. arr.push(text.slice(str, j));
  167. str = j;
  168. rows++;
  169. }
  170. }
  171. }
  172. arr.push(text.slice(str, text.length));
  173. return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数]
  174. },
  175. /**
  176. * 获取分享海报
  177. * @param array arr2 海报素材
  178. * @param string store_name 素材文字
  179. * @param string price 价格
  180. * @param function successFn 回调函数
  181. *
  182. *
  183. */
  184. PosterCanvas: function(arr2, store_name, price, successFn, errFun) {
  185. let that = this;
  186. const ctx = uni.createCanvasContext('myCanvas');
  187. ctx.clearRect(0, 0, 0, 0);
  188. /**
  189. * 只能获取合法域名下的图片信息,本地调试无法获取
  190. *
  191. */
  192. uni.getImageInfo({
  193. src: arr2[0],
  194. success: function(res) {
  195. console.log(res, 'getImageInfo')
  196. const WIDTH = res.width;
  197. const HEIGHT = res.height;
  198. ctx.drawImage(arr2[0], 0, 0, WIDTH, HEIGHT);
  199. ctx.drawImage(arr2[1], 0, 0, WIDTH, WIDTH);
  200. ctx.save();
  201. let r = 90;
  202. let d = r * 2;
  203. let cx = 40;
  204. let cy = 990;
  205. ctx.arc(cx + r, cy + r, r, 0, 2 * Math.PI);
  206. // ctx.clip();
  207. ctx.drawImage(arr2[2], cx, cy, d, d);
  208. ctx.restore();
  209. const CONTENT_ROW_LENGTH = 40;
  210. let [contentLeng, contentArray, contentRows] = that.textByteLength(store_name, CONTENT_ROW_LENGTH);
  211. if (contentRows > 2) {
  212. contentRows = 2;
  213. let textArray = contentArray.slice(0, 2);
  214. textArray[textArray.length - 1] += '……';
  215. contentArray = textArray;
  216. }
  217. ctx.setTextAlign('center');
  218. ctx.setFontSize(32);
  219. let contentHh = 32 * 1.3;
  220. for (let m = 0; m < contentArray.length; m++) {
  221. ctx.fillText(contentArray[m], WIDTH / 2, 820 + contentHh * m);
  222. }
  223. ctx.setTextAlign('center')
  224. ctx.setFontSize(48);
  225. ctx.setFillStyle('red');
  226. ctx.fillText('¥' + price, WIDTH / 2, 880 + contentHh);
  227. ctx.draw(true, function() {
  228. uni.canvasToTempFilePath({
  229. canvasId: 'myCanvas',
  230. fileType: 'png',
  231. destWidth: WIDTH,
  232. destHeight: HEIGHT,
  233. success: function(res) {
  234. uni.hideLoading();
  235. successFn && successFn(res.tempFilePath);
  236. },
  237. fail: function(err) {
  238. uni.hideLoading();
  239. errFun && errFun(err);
  240. }
  241. })
  242. });
  243. },
  244. fail: function(err) {
  245. uni.hideLoading();
  246. that.Tips({
  247. title: '无法获取图片信息'
  248. });
  249. errFun && errFun(err);
  250. }
  251. })
  252. },
  253. /**
  254. * 用户信息分享海报
  255. * @param array arr2 海报素材 1背景 0二维码
  256. * @param string nickname 昵称
  257. * @param string sitename 价格
  258. * @param function successFn 回调函数
  259. *
  260. *
  261. */
  262. userPosterCanvas: function(arr2, nickname, sitename, index, w, h, successFn) {
  263. let that = this;
  264. const ctx = uni.createCanvasContext('myCanvas' + index);
  265. console.log(ctx)
  266. ctx.clearRect(0, 0, 0, 0);
  267. /**
  268. * 只能获取合法域名下的图片信息,本地调试无法获取
  269. *
  270. */
  271. uni.getImageInfo({
  272. src: arr2[1],
  273. success: function(res) {
  274. const WIDTH = res.width;
  275. const HEIGHT = res.height;
  276. ctx.fillStyle = '#fff';
  277. ctx.fillRect(0, 0, w, h);
  278. ctx.drawImage(arr2[1], 0, 0, w, h);
  279. ctx.setTextAlign('left')
  280. ctx.setFontSize(12);
  281. ctx.setFillStyle('#333');
  282. // x:240 y:426
  283. let codex = 0.1906
  284. let codey = 0.7746
  285. let codeSize = 0.21666
  286. let namex = 0.4283
  287. let namey = 0.8215
  288. let markx = 0.4283
  289. let marky = 0.8685
  290. ctx.drawImage(arr2[0], w * codex, h * codey, w * codeSize, w * codeSize);
  291. if (w < 270) {
  292. ctx.setFontSize(8);
  293. } else {
  294. ctx.setFontSize(10);
  295. }
  296. ctx.fillText(nickname, w * namex, h * namey);
  297. if (w < 270) {
  298. ctx.setFontSize(8);
  299. } else {
  300. ctx.setFontSize(10);
  301. }
  302. ctx.fillText(sitename, w * markx, h * marky);
  303. ctx.save();
  304. ctx.draw(true, function() {
  305. uni.canvasToTempFilePath({
  306. canvasId: 'myCanvas' + index,
  307. fileType: 'png',
  308. quality: 1,
  309. success: function(res) {
  310. console.log(res)
  311. successFn && successFn(res.tempFilePath);
  312. }
  313. })
  314. });
  315. },
  316. fail: function(err) {
  317. uni.hideLoading();
  318. that.Tips({
  319. title: '无法获取图片信息'
  320. });
  321. }
  322. })
  323. },
  324. /*
  325. * 单图上传
  326. * @param object opt
  327. * @param callable successCallback 成功执行方法 data
  328. * @param callable errorCallback 失败执行方法
  329. */
  330. uploadImageOne: function(opt, successCallback, errorCallback) {
  331. let that = this;
  332. if (typeof opt === 'string') {
  333. let url = opt;
  334. opt = {};
  335. opt.url = url;
  336. }
  337. let count = opt.count || 1,
  338. sizeType = opt.sizeType || ['compressed'],
  339. sourceType = opt.sourceType || ['album', 'camera'],
  340. is_load = opt.is_load || true,
  341. uploadUrl = opt.url || '',
  342. inputName = opt.name || 'field';
  343. uni.chooseImage({
  344. count: count, //最多可以选择的图片总数
  345. sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有
  346. sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
  347. success: function(res) {
  348. //启动上传等待中...
  349. uni.showLoading({
  350. title: '图片上传中',
  351. });
  352. uni.uploadFile({
  353. url: HTTP_REQUEST_URL + '/api/' + uploadUrl + '/' + inputName,
  354. filePath: res.tempFilePaths[0],
  355. name: inputName,
  356. formData: {
  357. 'filename': inputName
  358. },
  359. header: {
  360. // #ifdef MP
  361. "Content-Type": "multipart/form-data",
  362. // #endif
  363. [TOKENNAME]: 'Bearer ' + store.state.app.token
  364. },
  365. success: function(res) {
  366. console.log(res, 'res22222222222222')
  367. uni.hideLoading();
  368. if (res.statusCode == 403) {
  369. that.Tips({
  370. title: res.data
  371. });
  372. } else {
  373. let data = res.data ? JSON.parse(res.data) : {};
  374. if (data.status == 200) {
  375. successCallback && successCallback(data)
  376. } else {
  377. errorCallback && errorCallback(data);
  378. that.Tips({
  379. title: data.message
  380. });
  381. }
  382. }
  383. },
  384. fail: function(res) {
  385. uni.hideLoading();
  386. that.Tips({
  387. title: '上传图片失败'
  388. });
  389. }
  390. })
  391. // pathToBase64(res.tempFilePaths[0])
  392. // .then(imgBase64 => {
  393. // console.log(imgBase64);
  394. // })
  395. // .catch(error => {
  396. // console.error(error)
  397. // })
  398. }
  399. })
  400. },
  401. serialize: function(obj) {
  402. var str = [];
  403. for (var p in obj)
  404. if (obj.hasOwnProperty(p)) {
  405. str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
  406. }
  407. return str.join("&");
  408. },
  409. getNowUrl: function() {
  410. const pages = getCurrentPages(),
  411. page = pages[pages.length - 1],
  412. query = this.serialize(page.options || {});
  413. return page.route + (query ? '?' + query : '');
  414. },
  415. /**
  416. * 处理服务器扫码带进来的参数
  417. * @param string param 扫码携带参数
  418. * @param string k 整体分割符 默认为:&
  419. * @param string p 单个分隔符 默认为:=
  420. * @return object
  421. *
  422. */
  423. // #ifdef MP
  424. getUrlParams: function(param, k, p) {
  425. if (typeof param != 'string') return {};
  426. k = k ? k : '&'; //整体参数分隔符
  427. p = p ? p : '='; //单个参数分隔符
  428. var value = {};
  429. if (param.indexOf(k) !== -1) {
  430. param = param.split(k);
  431. for (var val in param) {
  432. if (param[val].indexOf(p) !== -1) {
  433. var item = param[val].split(p);
  434. value[item[0]] = item[1];
  435. }
  436. }
  437. } else if (param.indexOf(p) !== -1) {
  438. var item = param.split(p);
  439. value[item[0]] = item[1];
  440. } else {
  441. return param;
  442. }
  443. return value;
  444. },
  445. // #endif
  446. /*
  447. * 合并数组
  448. */
  449. SplitArray(list, sp) {
  450. if (typeof list != 'object') return [];
  451. if (sp === undefined) sp = [];
  452. for (var i = 0; i < list.length; i++) {
  453. sp.push(list[i]);
  454. }
  455. return sp;
  456. },
  457. trim(str) {
  458. return String.prototype.trim.call(str);
  459. },
  460. $h: {
  461. //除法函数,用来得到精确的除法结果
  462. //说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  463. //调用:$h.Div(arg1,arg2)
  464. //返回值:arg1除以arg2的精确结果
  465. Div: function(arg1, arg2) {
  466. arg1 = parseFloat(arg1);
  467. arg2 = parseFloat(arg2);
  468. var t1 = 0,
  469. t2 = 0,
  470. r1, r2;
  471. try {
  472. t1 = arg1.toString().split(".")[1].length;
  473. } catch (e) {}
  474. try {
  475. t2 = arg2.toString().split(".")[1].length;
  476. } catch (e) {}
  477. r1 = Number(arg1.toString().replace(".", ""));
  478. r2 = Number(arg2.toString().replace(".", ""));
  479. return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
  480. },
  481. //加法函数,用来得到精确的加法结果
  482. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  483. //调用:$h.Add(arg1,arg2)
  484. //返回值:arg1加上arg2的精确结果
  485. Add: function(arg1, arg2) {
  486. arg2 = parseFloat(arg2);
  487. var r1, r2, m;
  488. try {
  489. r1 = arg1.toString().split(".")[1].length
  490. } catch (e) {
  491. r1 = 0
  492. }
  493. try {
  494. r2 = arg2.toString().split(".")[1].length
  495. } catch (e) {
  496. r2 = 0
  497. }
  498. m = Math.pow(100, Math.max(r1, r2));
  499. return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  500. },
  501. //减法函数,用来得到精确的减法结果
  502. //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
  503. //调用:$h.Sub(arg1,arg2)
  504. //返回值:arg1减去arg2的精确结果
  505. Sub: function(arg1, arg2) {
  506. arg1 = parseFloat(arg1);
  507. arg2 = parseFloat(arg2);
  508. var r1, r2, m, n;
  509. try {
  510. r1 = arg1.toString().split(".")[1].length
  511. } catch (e) {
  512. r1 = 0
  513. }
  514. try {
  515. r2 = arg2.toString().split(".")[1].length
  516. } catch (e) {
  517. r2 = 0
  518. }
  519. m = Math.pow(10, Math.max(r1, r2));
  520. //动态控制精度长度
  521. n = (r1 >= r2) ? r1 : r2;
  522. return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  523. },
  524. //乘法函数,用来得到精确的乘法结果
  525. //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  526. //调用:$h.Mul(arg1,arg2)
  527. //返回值:arg1乘以arg2的精确结果
  528. Mul: function(arg1, arg2) {
  529. arg1 = parseFloat(arg1);
  530. arg2 = parseFloat(arg2);
  531. var m = 0,
  532. s1 = arg1.toString(),
  533. s2 = arg2.toString();
  534. try {
  535. m += s1.split(".")[1].length
  536. } catch (e) {}
  537. try {
  538. m += s2.split(".")[1].length
  539. } catch (e) {}
  540. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
  541. },
  542. },
  543. // 获取地理位置;
  544. $L: {
  545. async getLocation() {
  546. // #ifdef APP-PLUS
  547. let status = await this.checkPermission();
  548. if (status !== 1) {
  549. return;
  550. }
  551. // #endif
  552. // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
  553. let status = await this.getSetting();
  554. if (status === 2) {
  555. this.openSetting();
  556. return;
  557. }
  558. // #endif
  559. this.doGetLocation();
  560. },
  561. doGetLocation() {
  562. uni.getLocation({
  563. success: (res) => {
  564. uni.removeStorageSync('CACHE_LONGITUDE');
  565. uni.removeStorageSync('CACHE_LATITUDE');
  566. uni.setStorageSync('CACHE_LONGITUDE', res.longitude);
  567. uni.setStorageSync('CACHE_LATITUDE', res.latitude);
  568. },
  569. fail: (err) => {
  570. // #ifdef MP-BAIDU
  571. if (err.errCode === 202 || err.errCode === 10003) { // 202模拟器 10003真机 user deny
  572. this.openSetting();
  573. }
  574. // #endif
  575. // #ifndef MP-BAIDU
  576. if (err.errMsg.indexOf("auth deny") >= 0) {
  577. uni.showToast({
  578. title: "访问位置被拒绝"
  579. })
  580. } else {
  581. uni.showToast({
  582. title: err.errMsg
  583. })
  584. }
  585. // #endif
  586. }
  587. })
  588. },
  589. getSetting: function() {
  590. return new Promise((resolve, reject) => {
  591. uni.getSetting({
  592. success: (res) => {
  593. if (res.authSetting['scope.userLocation'] === undefined) {
  594. resolve(0);
  595. return;
  596. }
  597. if (res.authSetting['scope.userLocation']) {
  598. resolve(1);
  599. } else {
  600. resolve(2);
  601. }
  602. }
  603. });
  604. });
  605. },
  606. openSetting: function() {
  607. uni.openSetting({
  608. success: (res) => {
  609. if (res.authSetting && res.authSetting['scope.userLocation']) {
  610. this.doGetLocation();
  611. }
  612. },
  613. fail: (err) => {}
  614. })
  615. },
  616. async checkPermission() {
  617. let status = permision.isIOS ? await permision.requestIOS('location') :
  618. await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
  619. if (status === null || status === 1) {
  620. status = 1;
  621. } else if (status === 2) {
  622. uni.showModal({
  623. content: "系统定位已关闭",
  624. confirmText: "确定",
  625. showCancel: false,
  626. success: function(res) {}
  627. })
  628. } else if (status.code) {
  629. uni.showModal({
  630. content: status.message
  631. })
  632. } else {
  633. uni.showModal({
  634. content: "需要定位权限",
  635. confirmText: "设置",
  636. success: function(res) {
  637. if (res.confirm) {
  638. permision.gotoAppSetting();
  639. }
  640. }
  641. })
  642. }
  643. return status;
  644. },
  645. }
  646. }